【问题标题】:How to perform task after mixed async operation( callback & promise ) finished?混合异步操作(回调和承诺)完成后如何执行任务?
【发布时间】:2016-06-02 03:08:50
【问题描述】:

我正在编写一些 nodejs 应用程序。我的应用程序依赖于一些 npm 模块。

在一个task中,涉及到两个async操作,这两个async操作是callback和promise的形式。下面我放了一些示例代码:

// the task which should be performed after async operation
var myTask = function(){
  // do something
}

// first async operation in the form of callback
cbapi(myTask)

// second async operation in the form of promise
promiseapi()
.then(myTask)

在上面的例子中,myTask 将在第一次异步和第二次异步操作完成时执行两次。但我想要的是仅在完成两个异步操作后才执行一次。

有什么办法吗?

【问题讨论】:

  • 不要混用回调和promise,promisify回调api然后调用promisified api
  • 没有看到代码很难帮助你,但 Esailija 所说的就像一个经验法则。

标签: node.js asynchronous callback promise


【解决方案1】:

围绕回调函数调用构造一个新的 Promise,并在两个调用中使用 Promise.all

Promise.all([new Promise(resolve => cbapi(resolve)), promiseapi()])
.then(myTask)
.catch(e => console.error(e));

myTask 将使用包含两次调用结果的数组进行调用。

【讨论】:

  • 这样如果cbapi 导致错误,它仍然会解决promise。它应该拒绝。
  • @Louy 正如所写,OP 的 cbapi 无法异步失败(在它返回之后),所以考虑到这些限制,我的回答是合适的。为了能够异步失败,cbapi 需要接受两个参数:一个成功回调和一个失败回调,然后我们用new Promise((resolve, reject) => cbapi(resolve, reject)) 包裹它。
  • 你怎么知道cbapi 不会失败?如果它基于问题中的示例代码,那么我认为这是一个错误的假设。回调有一个应该遵循的标准。
  • 我的回答是基于“是”这个问题。 OP 的示例代码显示希望在两次异步操作之后运行 myTask,而不管看起来是否有任何异步失败,因为 myTask 不带任何参数。
【解决方案2】:

正如 @esaukuha 所建议的,您应该承诺您的回调 API,然后使用它们。

new Promise((resolve, reject) => 
  cbapi((err, result) => {
    if (err) reject(err);
    else resolve(result);
  })
)
  .then(myTask) // ... chain

我有一个小npm module 就是为了这个。

import fromCallback from 'promise-cb/from';
fromCallback(cb => cbapi(cb))
  .then(myTask) // ... chain

【讨论】:

  • cbapi 确实有一个论点。我的答案只传递了一个参数(lambda 函数。)
  • 对,我的意思是 myTask 不接受任何参数,而您假设一个错误参数和一个结果参数。
  • myTask 在这里不接受任何参数。我只是从cbapi 创建一个标准承诺,并在完成后调用myTask
  • 是的,但您假设 cbapi 使用您编造的某些参数调用其回调,而 OP 从未提及。
  • 正如我所提到的,这是一个标准。除非您有充分的理由不这样做,否则您应该始终遵循(并假设遵循)标准。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多