赞
踩
采集数据时过程很慢,导致无法继续进行其他任务,,避免主业务被长时间阻塞,故而将其提交给异步任务,当任务完成通知客户端即可
前端业务:
由于本系统采用iframe结构,为避免点击其他页面业务中断,所以业务在父页面执行,
1.用户在子页面点击采集按钮调用父级方法
- function to_collect(ids) {
- window.parent.startCollect(ids);
- }
2.父级页面进行socket链接,当收到服务器处理完任务消息时关闭socket并通知用户结果
- function startCollect(ids)
- {
- var wsServer = 'ws://127.0.0.1:5432';
- var websocket = new WebSocket(wsServer);
- var inter_val = 0;
- websocket.onopen = function (evt) {
- console.log("Connected to WebSocket server.");
- var data = {ids:ids};
- data = JSON.stringify(data);
- websocket.send(data);
-
- //设置心跳,避免服务器断开
- inter_val = setInterval(function () {
- websocket.send('hello');
- }, 50000)
- };
-
- websocket.onclose = function (evt) {
- console.log("Disconnected");
- };
-
- websocket.onmessage = function (evt) {
- console.log('Retrieved data from server: ' + evt.data);
- if (isJson(evt.data)) {
- var res = JSON.parse(evt.data);
- if(res.code == 0){
- alert("采集条数:"+res.msg)
- websocket.close();
- clearInterval(inter_val);//关闭定时器
- }
- }
-
-
-
- };
-
- websocket.onerror = function (evt, e) {
- console.log('Error occured: ' + evt.data);
- };
- }
-
-
- /**
- * 判断是否json
- * @param $string
- * @returns {boolean}
- */
- function isJson($string)
- {
- try {
- if(typeof JSON.parse($string) == 'object')
- return true;
- return false;
- } catch (e) {
- console.log(e);
- return false;
-
- }
- }
服务端
1. 收到前端发来的数据,调用model进行业务处理,然后通知客户端
- <?php
- namespace app\http;
-
- use app\common\model\Collect;
- use think\worker\Server;
- use Workerman\Lib\Timer;
- use Workerman\Worker as W;
-
- class Worker2 extends Server
- {
- protected $socket = 'websocket://0.0.0.0:5432';
- protected $option = [
- 'count'=> 4,
- ];
-
- /**
- * 每个进程启动
- * @param $worker
- */
-
-
- public function onWorkerStart($worker)
- {
-
-
- // 心跳间隔55秒
- define('HEARTBEAT_TIME', 55);
- Timer::add(1, function()use($worker){
- $time_now = time();
- foreach($worker->connections as $connection) {
- // 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间
- if (empty($connection->lastMessageTime)) {
- $connection->lastMessageTime = $time_now;
- continue;
- }
- // 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接
- if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
- $connection->close();
- }
- }
- });
- }
-
- public function onMessage($connection,$data)
- {
- global $worker;
- // 判断当前客户端是否已经验证,即是否设置了uid
- if(!isset($connection->uid))
- {
- // 没验证的话把第一个包当做uid(这里为了方便演示,没做真正的验证)
- $connection->uid = ip2long($connection->getRemoteIp()).time().rand(1,9999);
- /* 保存uid到connection的映射,这样可以方便的通过uid查找connection,
- * 实现针对特定uid推送数据
- */
- $worker->uidConnections[$connection->uid] = $connection;
- $connection->send('login success, your uid is ' . $connection->uid);
- }
- $ids = json_decode($data,true)['ids'] ?? 0;
- if ($ids)
- {
- $collect_model = new Collect();
- $res = $collect_model->getNewestArticle($ids);
- $res = json_encode(['code' => 0,'msg' =>$res]);
- $connection->send($res);
- }
-
- // 给connection临时设置一个lastMessageTime属性,用来记录上次收到消息的时间
- $connection->lastMessageTime = time();
- //$connection->send('receive success');
- echo $data;
- echo "\n";
- }
-
- public function onConnect($connection)
- {
-
- }
-
- /**
- * 当连接断开时触发的回调函数
- * @param $connection
- */
- public function onClose($connection)
- {
- global $worker;
- if(isset($connection->uid))
- {
- // 连接断开时删除映射
- unset($worker->uidConnections[$connection->uid]);
- }
- }
- /**
- * 当客户端的连接上发生错误时触发
- * @param $connection
- * @param $code
- * @param $msg
- */
- public function onError($connection, $code, $msg)
- {
- echo "error $code $msg\n";
- }
-
-
- // 针对uid推送数据
- public function sendMessageByUid($uid, $message)
- {
- global $worker;
- if(isset($worker->uidConnections[$uid]))
- {
- $connection = $worker->uidConnections[$uid];
- $connection->send($message);
- return true;
- }
- return false;
- }
-
-
- }
启动 workerman
执行结果
thinkphp5中如何开启workman请参照https://blog.csdn.net/flysnownet/article/details/96475927
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。