关于 promise 的一个问题

2014-06-06 16:25:40 +08:00
 ryanking8215
有个需求是发送消息后等待消息,如果超时后,再次发送,直到超时时间超过一定值,如果期间有收到消息,则算成功。

我用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()函数啊?
4837 次点击
所在节点    Node.js
7 条回复
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
2014-06-06 16:56:06 +08:00
刚又看了下,觉得bluebird retry文档里的例子应该可以解决楼主的问题。
bluebird可以直接用Promise.promisifyAll来把一个模块所有的函数都变为async的,挺方便,功能强大,并且执行效率超过callback机制的async,可谓promise神器
andyhu
2014-06-06 16:56:29 +08:00
更正,是bluebird *timeout
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
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
2014-06-06 17:28:18 +08:00
貌似最近bluebird很火,找个时间看一下
rekey
2014-06-09 13:34:27 +08:00
还是 ES6 好玩啊。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/116121

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX