国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

Django+Vue實現WebSocket連接的示例代碼

2019-11-19 11:26:42
字體:
來源:轉載
供稿:網友

近期有一需求:前端頁面點擊執行任務,實時顯示后端執行情況,思考一波;發現 WebSocket 最適合做這件事。

效果

測試 ping www.baidu.com 效果

點擊連接建立ws連接

后端實現

所需軟件包

后端主要借助Django Channels 實現socket連接,官網文檔鏈接

這里想實現每個連接進來加入組進行廣播,所以還需要引入 channels-redis 。

pip

channels==2.2.0channels-redis==2.4.0

引入

settings.py

INSTALLED_APPS = [  'django.contrib.admin',  'django.contrib.auth',  'django.contrib.contenttypes',  'django.contrib.sessions',  'django.contrib.messages',  'django.contrib.staticfiles',  'rest_framework.authtoken',  'rest_framework',        ...  'channels',]# Redis配置REDIS_HOST = ENV_DICT.get('REDIS_HOST', '127.0.0.1')REDIS_PORT = ENV_DICT.get('REDIS_PORT', 6379)CHANNEL_LAYERS = {  "default": {    "BACKEND": "channels_redis.core.RedisChannelLayer",    "CONFIG": {      "hosts": [(REDIS_HOST, REDIS_PORT)],    },  },}

代碼

apps/consumers.py

新建一個消費處理

實現: 默認連接加入組,發送信息時的處理。

from channels.generic.websocket import WebsocketConsumerclass MyConsumer(WebsocketConsumer):  def connect(self):    """    每個任務作為一個頻道    默認進入對應任務執行頻道    """    self.job_name = self.scope['url_route']['kwargs']['job_name']    self.job_group_name = 'job_%s' % self.job_name    async_to_sync(self.channel_layer.group_add)(      self.job_group_name,      self.channel_name    )    self.accept()  def disconnect(self, close_code):    async_to_sync(self.channel_layer.group_discard)(      self.job_group_name,      self.channel_name    )  # job.message類型處理  def job_message(self, event):    # 默認發送收到信息    self.send(text_data=event["text"])

apps/routing.py

ws類型路由

實現:ws/job/<job_name>由 MyConsumer 去處理。

from . import consumersfrom django.urls import pathfrom channels.routing import ProtocolTypeRouter, URLRouterfrom channels.sessions import SessionMiddlewareStackapplication = ProtocolTypeRouter({  'websocket': SessionMiddlewareStack(    URLRouter(     [       path('ws/job/<str:job_name>', consumers.MyConsumer)     ]    )  ),})

apps/views.py

在執行命令中獲取 webSocket 消費通道,進行異步推送

  • 使用異步推送async_to_sync是因為在連接的時候采用的異步連接,所以推送必須采用異步推送。
  • 因為執行任務時間過長,啟動觸發運行時加入多線程,直接先返回ok,后端運行任務。
from subprocess import Popen,PIPEimport threadingdef runPopen(job):  """  執行命令,返回popen  """  path = os.path  Path = path.abspath(path.join(BASE_DIR, path.pardir))  script_path = path.abspath(path.join(Path,'run.sh'))  cmd = "sh %s %s" % (script_path, job)  return Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)def runScript(job):  channel_layer = get_channel_layer()  group_name = "job_%s" % job  popen = runPopen(job)  while True:    output = popen.stdout.readline()    if output == '' and popen.poll() is not None:      break    if output:      output_text = str(output.strip())      async_to_sync(        channel_layer.group_send        )(          group_name,           {"type": "job.message", "text": output_text}        )    else:      err = popen.stderr.readline()      err_text = str(err.strip())      async_to_sync(        channel_layer.group_send        )(          group_name,          {"type": "job.message", "text": err_text}        )      breakclass StartJob(APIView):   def get(self, request, job=None):    run = threading.Thread(target=runScript, args=(job,))    run.start()    return HttpResponse('ok')

apps/urls.py

get請求就能啟動任務

urlpatterns = [        ...  path('start_job/<str:job>', StartJob.as_view())]

前端實現

所需軟件包

vue-native-websocket 

代碼實現

plugins/vueNativeWebsocket.js

import Vue from 'vue'import VueNativeSock from '../utils/socket/Main.js'export default function ({ store }) { Vue.use(VueNativeSock, 'http://localhost:8000/ws/job', {connectManually: true,});}

nuxt.config.js

配置文件引入, 這里我使用的是 nuxt 框架

 plugins: [    {     src: '@/plugins/vueNativeWebsocket.js',     ***: false    },  ],

封裝 socket

export default (connection_url, option) => {  // 事件  let event = ['message', 'close', 'error', 'open'];  // 拷貝選項字典  let opts = Object.assign({}, option);  // 定義實例字典  let instance = {   // socket實例   socket: '',   // 是否連接狀態   is_conncet: false,   // 具體連接方法   connect: function() {    if(connection_url) {     let scheme = window.location.protocol === 'https:' ? 'wss' : 'ws'     connection_url = scheme + '://' + connection_url.split('://')[1];     this.socket = new WebSocket(connection_url);     this.initEvent();    }else{     console.log('wsurl

主站蜘蛛池模板:
项城市|
黄石市|
望都县|
阿荣旗|
瓦房店市|
萝北县|
凤庆县|
南京市|
固阳县|
兴国县|
华容县|
凤山市|
定西市|
拉萨市|
江永县|
商都县|
祁东县|
保德县|
阿克苏市|
洛宁县|
烟台市|
高邮市|
班玛县|
兴和县|
界首市|
聂拉木县|
霍林郭勒市|
揭阳市|
赤壁市|
万盛区|
曲靖市|
青龙|
随州市|
临猗县|
临夏县|
保德县|
巨鹿县|
保德县|
中西区|
阿克|
博湖县|