在承诺和拒绝中为回调添加超时

Adding a timeout for a callback within a promise and rejecting

我正在将 socket.io 的 emit 函数转换为这样的承诺。

var io = require("socket.io-client")
var Promise = require("bluebird")
var _ = require("underscore")

io.emitAsync = function(event, payload){
  return new Promise(function (resolve, reject) {
    return io.emit(event, payload, function(){
      var args = _.toArray(arguments)
      if(args[0]) reject(new Error(args[0]))
      resolve.apply(null, args)
    })
  })
}

我无法使用 promiseify,因为 io.emit 回调没有 return 节点式回调签名。 The first argument can't be an error object. 所以计划是传递一个字符串错误消息,如果第一个参数是 truthy,上面的承诺将拒绝。这一切都很好,花花公子,这就是问题所在。

如果您在 socket.on 中没有 return callback,那么上面的承诺永远不会 resolvereject 任何东西。所以我需要的是这个 callback 的超时,如果在指定的时间内没有任何结果,那么它将 reject(new Error("timeout"))。问题是我不知道该怎么做。理想情况下,我可以将 seconds 设置为在上面的函数中等待,或者如果知道我想要 resolve 的给定事件没有回调,那么理想情况下它是 emitAsync 本身的参数.想法?

你当然可以使用 Bluebird timeout method

较低级别的解决方案是使用 setTimeout:

new Promise(function (resolve, reject) {
  io.emit(event, payload, function(err){
    if(err) reject(new Error(err))
    resolve(_.toArray(arguments).slice(1));
  })
  setTimeout(function(){
    reject(new Error("timeout"));
  }, seconds*1000);
})