510°

从零开始搭建django前后端分离项目 系列四(实战之实时进度)

本项目实现了任务执行的实时进度查询

实现方式

前端websocket + 后端websocket + 后端redis订阅/发布

实现原理

任务执行后,假设用变量num标记任务执行的进度,然后将num发布为订阅的消息保存到redis队列,比如 redis_helper.public('当前任务进度为 %s' %num),django的websocket视图在特定频道订阅消息num并利用websocket协议将消息实时推送到前端,完成前端实时进度展示。

实现代码

redis订阅/发布:

class RedisHelper:
    def __init__(self, key):
        self.__conn = redis.Redis(host=config.host2, port=config.port2, db=config.db2)
        self.chan_sub = key
        self.chan_pub= key

    #发送消息
    def public(self,msg):
        # logger.info(msg)
        self.__conn.publish(self.chan_pub,msg)
        return True
    #订阅
    def subscribe(self):
        #打开收音机
        pub = self.__conn.pubsub()
        #调频道
        pub.subscribe(self.chan_sub)
        #准备接收
        pub.parse_response()
        return pub

 

django视图:

@accept_websocket
def analyze(request):
    if not request.is_websocket():  # 判断是不是websocket连接
        file_path=request.GET.get('file_path')
        file_path_id = request.GET.get('file_path_id')
        file=File.objects.get_or_create(id=file_path_id)[0]
        jobname=file.name
        job = Job(name=jobname,file=file)
        job.save()
        channel = job.id
        result = cluster_analyze_task.delay(channel,file_path,file_path_id)
        taskid=result.id
        job.task_id=taskid
        job.save()
        return JsonResponse({'taskid': taskid,'channel': channel},safe=False)
    else:
        for message in request.websocket:
            obj = RedisHelper(message)
            redis_sub = obj.subscribe()

            while True:
                msg = redis_sub.parse_response()
                msg = msg[2]
                request.websocket.send(msg)  # 发送消息到客户端
                if msg.decode()=='end':
                    break

前端websocket:

vue的method中增加如下方法:
initWebSocket() { // 初始化weosocket
  // ws地址
  const wsuri = 'ws://10.39.211.151:8000/app/analyze/';
  this.websock = new WebSocket(wsuri);
  this.websock.onopen = this.websocketonopen;
  this.websock.onmessage = this.websocketonmessage;
  this.websock.onclose = this.websocketclose;
},
websocketonmessage(e) { // 数据接收
  // console.log(e.data);
},
websocketsend(agentData) { // 数据发送
  // 若是ws开启状态
  if (this.websock.readyState === this.websock.OPEN) {
    this.websock.send(agentData)
  }
  // 若是 正在开启状态,则等待300毫秒
  else if (this.websock.readyState === this.websock.CONNECTING) {
    let that = this;// 保存当前对象this
    setTimeout(function() {
      that.websock.send(agentData)
    }, 300);
  }
  // 若未开启 ,则等待500毫秒
  else {
    this.initWebSocket();
    let that = this;// 保存当前对象this
    setTimeout(function() {
      that.websock.send(agentData)
    }, 500);
  }
},
websocketonopen() {
  // alert('数据发送中...');
  console.log('WebSocket连接成功');
},
websocketclose(e) { // 关闭
  console.log('connection closed (' + e.code + ')');
}

在创建时进行初始化
created() {
  this.initWebSocket();
},

 

效果图

 

原文链接:https://www.cnblogs.com/dotafeiying/p/9669070.html

全部评论: 0

    我有话说: