V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
yazoox
V2EX  ›  JavaScript

请教一个编程技巧,有没有办法把 websocket 的通讯装到 Promise 里面去?

  •  
  •   yazoox · 2020-08-26 22:24:55 +08:00 · 2869 次点击
    这是一个创建于 1300 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在有一个需求,要使用 websocket 传输数据,时间大概几秒钟。
    想在传输数据的时候,同时装备下一份数据。准备的时候,也大概几秒钟。

    所以,就在想,能否把这两块并行起来。

    初步想法 /方法,就是用 Promise.all ,但貌似代码不是很好写。
    因为 websocket 的调用,什么 onmessage 等等,不太好放入到 promise 里面去。

    有没有兄弟知道怎么做?或者有其它更好的方法?比如 multi-threads?

    谢谢。

    p.s. JavaScript/TypeScript 前端

    16 条回复    2020-08-31 21:25:05 +08:00
    Jirajine
        1
    Jirajine  
       2020-08-26 22:34:18 +08:00 via Android
    jiangzm
        2
    jiangzm  
       2020-08-26 22:51:47 +08:00
    你弄个发送队列不就好了,ws 从队列拿数据发送,组装的数据不断扔到队列。

    后面你要封装 Promise 是要干嘛,没看懂, 可以贴了伪代码示例一下。
    fivge
        3
    fivge  
       2020-08-27 09:03:29 +08:00
    rxjs
    yazoox
        4
    yazoox  
    OP
       2020-08-27 09:42:43 +08:00
    @jiangzm #2 不太好贴。legacy 的项目,一大堆代码全挤在一起。

    基本流程就是先传输文件过去,传输完了,如果成功,再传输证书。即,onmessage 里面,收到成功的回复后,再发送证书。

    但大家知道,申请证书,调用 api 也是需要时间的。
    所以,想在发送文件时,异步调用函数申请证书。等收到文件传输成功消息 /响应后,就能直接发送证书了。
    yazoox
        5
    yazoox  
    OP
       2020-08-27 09:47:36 +08:00
    @jiangzm #2 看懂你的意思了。

    可惜,我们这个逻辑 /流程,当初设计的时候,就有严格的顺序。握手-验证双方身份-发送文件-发送证书-……
    有顺序的。相当于“同步”执行。
    azcvcza
        6
    azcvcza  
       2020-08-27 10:02:55 +08:00
    ```
    onmessage = function(data){
    if(data.type === '某种类型'){
    new Promise(resolve=>{
    resolve(axios.post('xxx'))
    }).then(res=>{
    // get auth
    websocket.send()
    })
    }
    }
    ```
    大致逻辑这样?
    peterjose
        7
    peterjose  
       2020-08-27 10:46:19 +08:00
    没太听懂你在说啥 但是 rxjs-websocket 估计能满足你
    libook
        8
    libook  
       2020-08-27 11:13:16 +08:00
    没有代码,没法提供方案。

    数据量不大到至于爆掉引擎内存空间的话,可以准备两个线程(比如 Web Workers )、一个队列,一个线程持续准备数据并将待发送的数据插入到队列中,另一个线程不断从队列中读取数据发送。如果你用内存存储队列且怕内存爆掉,可以在准备数据的过程里每次循环都检查一下队列大小,如果超出阈值就暂停一段时间。

    Promise 是在一个线程内控制异步 IO 的,Promise.all 不知道你想怎么用,如果单纯吧准备和发送数据的过程扔到里面估计是所有要处理的数据同时准备和发送了,你要是对数据没有先后顺序要求的话也不是不行。Promise 提升效率的关键在于异步 API 异步执行,同步 API 用了 Promise 也不会异步执行,这时候就得考虑多线程了。
    hitaoguo
        9
    hitaoguo  
       2020-08-27 11:24:45 +08:00
    // 把传输文件封装成一个 Promise
    const sendFile = () => Promise.resolve()
    // 申请证书也封装一下
    const requestCert = () => Promise.resolve()
    const sendCert = () => { }
    // 最后通过 Promise.All ,当文件传输好了,并且证书也申请下来了的时候,再发送证书
    Promise.all([sendFile(), requestCert()]).then(sendCert)
    qyvlik
        10
    qyvlik  
       2020-08-27 15:56:49 +08:00
    jiangzm
        11
    jiangzm  
       2020-08-28 00:30:10 +08:00
    @yazoox #4 这很简单啊,异步发送文件和异步请求证书就行,然后在 onmessage 里面同步等待请求证书的结果
    code: https://gist.github.com/jiangzm/4474f2c2f601b23d306235b2233fbe03
    preview: <img src="https://s1.ax1x.com/2020/08/28/d5rJOg.png" alt="d5rJOg.png" border="0" />
    jiangzm
        12
    jiangzm  
       2020-08-28 00:34:50 +08:00
    jiangzm
        13
    jiangzm  
       2020-08-28 00:35:50 +08:00
    yazoox
        14
    yazoox  
    OP
       2020-08-28 15:32:51 +08:00
    @jiangzm
    谢谢。你的这个方法是可以的。
    今天学习到了一招,原来 promise 可以直接 assgin 给一个变量,调用后不管。
    在后面需要的时候,await promise 变量就可以了。
    yazoox
        15
    yazoox  
    OP
       2020-08-31 10:17:47 +08:00
    @jiangzm 这个方法,在使用过程中,还碰到一个问题。就是 try-catch 放在哪里?
    我们并不能保证 requestCert 一定成功,所以,Promise 内部的调用可能需要错误处理, throw exception 。
    错误捕获 /try-catch,是放在 L35 还是 L41 呢?因为 Promise 的启动和检查,分离了。
    jiangzm
        16
    jiangzm  
       2020-08-31 21:25:05 +08:00
    @yazoox #15 有两个改法,一是把 requestCert 里面 fetch 请求的 catch 加上,catch 里面 resolve 空字符串出来即可,还有种方式就是把 async-await 写法改成传统链式调用,即:certPromise.then(res => ws.send(cert)).catch(ex => console.log(ex));

    另外对于不稳定或易超时的接口要加入重试机制
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3395 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 11:53 · PVG 19:53 · LAX 04:53 · JFK 07:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.