【问题标题】:Is there a replacement for the deprecated deferred.callback?是否有已弃用的 deferred.callback 的替代品?
【发布时间】:2015-01-26 19:03:50
【问题描述】:

问题

我发现在我的代码中通常会出现以下相当冗长的模式,当我包含的库为我提供难以promisify 的对象时:

var object = crummyLibrary.create();
return new Promise(function(resolve, reject){
  object.method('foo', function(err, bar){
    if(err){
      reject(err);
    }else{
      resolve(bar);
    }
  });
});

这在以前使用Promise.defer() 时不那么冗长:

var deferred = Promise.defer();
object.method('foo', deferred.callback);
return deferred.promise;

但这现在已经被弃用了(有充分的理由),但我还没有找到一个很好的替代这个模式。我知道有这个:

return Promise.promisify(object.method, object)('foo');

但是因为context/receiver的传递,感觉很hacky和fiddely。

我在寻找什么

我希望有一些东西可以取代旧的 deferred.callback,可能是这样的:

var promise = new Promise;
object.method('foo', promise.callback);
return promise;

或者可能:

return new Promise(function(resolve, reject, callback){
  object.method('foo', callback);
});

或者,有人向我指出我一直“做错了”。

【问题讨论】:

  • 我不知道您是否注意到,但 Petka (Esailija) 已将 Promise.fromNode 添加到库中以供您使用 - 无论如何,这就是您应该在您的案例中使用的内容。
  • 我注意到了。请参阅 Esailija 回答下方的对话。 :)

标签: node.js asynchronous promise bluebird


【解决方案1】:

从 2.9.0 开始,Bluebird 附带了一个 .fromNode 方法,可以更快地对行为不端的库进行动态承诺:

Promise.fromNode(object.method.bind(object, "foo"))

我想可以实现以下内容:

return Promise.fromNodeFunction(function(callback){
  object.method('foo', callback);
});

只需要想一个不那么冗长的更好的名字......

自己实现:

Promise.fromNodeFunction = function(resolver) {
    var d = Promise.defer();
    try {
        resolver(d.callback);
    } catch (e) {
        d.reject(e);
    }
    return d.promise;
};

这是最可取的,因为它现在是 3 行,但使用箭头函数时它是单行:

return Promise.fromNodeFunction(callback => object.method("foo", callback))

它也适用于绑定:

return Promise.fromNodeFunction(object.method.bind(object, "foo"))

【讨论】:

  • 他的重点是避免使用 .defer() ,因为有人弃用它(有充分的理由):P
  • 你的想法很有趣,尽管你的实现讽刺地使用了Promise.defer。我想我会使用这个解决方案(使用更好的实现,然后我会编辑到你的答案中)。
  • 请原谅我在这里问,但你能看看并可能回答这个问题:stackoverflow.com/questions/28114180/… 吗?我在您的个人资料中看到了指向github.com/petkaantonov/bluebird/wiki/Optimization-killers 的链接,甚至可能您是本文的作者
  • @Avaq bluebird 2.9.0 有 Promise.fromNode
  • 我刚刚注意到它是文档中的 my 示例代码。我感到很荣幸。这是second time,我通过 Stack Overflow 问题为 Bluebird 做出了贡献。哦,我也刚刚意识到你是 Petka。哎呀。我猜你使用Promise.defer 是完全正确的,我现在闭嘴。 :$
【解决方案2】:

好吧,promisify 意味着在您的应用初始化时调用一次。您可以使用promisifyAll 一次性将整个 API 转换为 Promisified API。

Promise.promisifyAll(app.auth);

这将允许您在应用程序中的任何时间在app.auth 上使用任何方法作为返回承诺的方法:

app.auth.authenticateAsync("local").then(function(res){ // preserves context
    // handle result
});

另请注意,promisifypromisifyAll 比使用 new Promise 快得多,并且因为它们利用动态重新编译技术和其他各种优化,所以最好使用它们(但仅限于初始化时)。

【讨论】:

  • 嗨本杰明,感谢您的回答,但这不是我要找的。我在任何可能的情况下都使用promisifyAll,但有时库会为我提供它们没有公开构造函数或原型的对象(想想:function(){return {...}})。在这些情况下,我需要即时承诺。我很抱歉没有在我的问题中指定这一点。我会编辑它。
  • 在这种情况下不 - 没有直接替换您使用的模式。您可以继续使用.defer() 一段时间,当/如果它被删除时,您可以对其进行填充。
猜你喜欢
  • 2020-10-08
  • 1970-01-01
  • 2013-04-28
  • 1970-01-01
  • 2019-04-05
  • 1970-01-01
  • 2016-05-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多