V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ryanking8215
V2EX  ›  Node.js

关于 promise 的一个问题

  •  
  •   ryanking8215 · 2014-06-06 16:25:40 +08:00 · 4949 次点击
    这是一个创建于 3822 天前的主题,其中的信息可能已经有所发展或是发生改变。
    有个需求是发送消息后等待消息,如果超时后,再次发送,直到超时时间超过一定值,如果期间有收到消息,则算成功。

    我用q实现promise,但是有点费劲,代码又变成了嵌套的了。
    如下:
    Q.timeout(send(msg),timeout1)
    .then(function(rsp){
    // here is fulfilled
    )
    .catch(function(err)) {
    if (err.code==='ETIMEOUT') {
    Q.timeout(send(msg),timeout2).then()... // md,这里又来了
    }
    else {
    // here is rejected
    }
    }

    换言之,就是有若干个promise,顺序执行,如果成功了则fulfilled,如果失败了执行下一个,
    直到promise都完成。

    有没有好的方法,是不是要为Q添加一个Q.once()函数啊?
    7 条回复    2014-06-09 13:34:27 +08:00
    andyhu
        1
    andyhu  
       2014-06-06 16:52:12 +08:00
    用bluebird吧,我见Q一次推荐一次bluebird。。
    对楼主的需求还不是特别的清楚,可以再仔细解释下吗?
    关于timeout可以参考下bluebird文档:
    https://github.com/petkaantonov/bluebird/blob/master/API.md#timeoutint-ms--string-message---promise
    关于为何要用bluebird而不用Q,可以搜索下各类vs贴
    andyhu
        2
    andyhu  
       2014-06-06 16:56:06 +08:00
    刚又看了下,觉得bluebird retry文档里的例子应该可以解决楼主的问题。
    bluebird可以直接用Promise.promisifyAll来把一个模块所有的函数都变为async的,挺方便,功能强大,并且执行效率超过callback机制的async,可谓promise神器
    andyhu
        3
    andyhu  
       2014-06-06 16:56:29 +08:00
    更正,是bluebird *timeout
    bolasblack
        4
    bolasblack  
       2014-06-06 17:09:20 +08:00
    Q.timeout(send(msg),timeout1).then(function(rsp){
    // here is fulfilled
    })
    .catch(function(err)) {
    if (err.code==='ETIMEOUT') {
    return Q.timeout(send(msg),timeout2) // 你在这里可以直接 return
    } else {
    return Q.reject(err) // 如果返回的是被 reject 的 promise ,那么是不会走到下面的 .then 里去的
    }
    })
    .then(function(result) {
    // 在 catch 里 return 的 promise 如果成功了会走到这里
    })
    .catch(function(err) {
    // 在 catch 里 return 的 promise 如果失败了会走到这里
    })
    ryanking8215
        5
    ryanking8215  
    OP
       2014-06-06 17:21:56 +08:00
    你好,问题就在这里,如果要发送N次,我就要在代码里写N次的Q.timeout(send(msg))。

    现在我解决这个问题了,用递归。

    一开始思路错了,想着让Q来解决问题,现在碰到超时,就用递归再调用send(msg)就好了,控制递归的结束条件,恩,如下所示:

    function send(msg,timeout,defer){
    if (timeout>4000) {
    defer.reject(new Error("Timeout"))
    return
    }
    // 如果超时了,就继续发送
    var id = setTimeout(function({
    self.send(msg,timeout*2,defer) // 超时后send again
    }),timeout)

    // 以下是发送和接收消息,要么defer.resolve(),要么defer.resolve()
    }

    function sendMsg(msg) {
    var defer = Q.defer()
    this.send(msg,500,defer)
    return defer.promise
    }
    ryanking8215
        6
    ryanking8215  
    OP
       2014-06-06 17:28:18 +08:00
    貌似最近bluebird很火,找个时间看一下
    rekey
        7
    rekey  
       2014-06-09 13:34:27 +08:00
    还是 ES6 好玩啊。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4745 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 42ms · UTC 09:46 · PVG 17:46 · LAX 01:46 · JFK 04:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.