首页 > 解决方案 > 检测函数启动的所有异步工作何时完成

问题描述

我需要知道函数调用启动的所有工作何时完成。

我有一个函数,它将另一个函数作为参数并调用该函数:

function outer(inner) {
   inner()
}

内部函数可能会启动一些异步行为:

function inner() {
   new Promise(...)
   new Promise(...)
   new Promise(...)
   requestAnimationFrame(...)
   requestAnimationFrame(...)
}

我知道如何Promise.all运作。但是对于 Promise.all,你需要传递一系列的 Promise。我希望我的函数不知道内部函数内部发生的细节。由于 javascript 使用回调而不是 Promise 来处理大量异步行为,因此 Promise.all 无法处理所有异步工作情况。

从外部函数的范围来看,有什么方法可以检测内部函数的异步和同步工作是否完成,并将此行为应用于我传入的任何函数outer

function outer(inner) {
   inner.allWorkComplete(() => ...do more work)
   inner();
}

我试图避免将其硬编码到内部函数中,因为这违背了构建更高阶函数来处理allWorkComplete事件的意义。

这只是javascript中的反模式吗?

标签: javascriptasynchronouspromise

解决方案


我希望我的函数不知道内部函数内部发生的细节。

这是不可能的[1]
内部函数需要合作并告诉您何时完成 - 通常,它通过返回适当的承诺来做到这一点。

1:至少不是没有很多努力。您需要控制整个环境,以便检测何时调用任何异步原语。

这只是javascript中的反模式吗?

是的。执行任何异步工作的函数要么需要自己处理完成(如果其他人不感兴趣),要么提供一种监听它的方法。

在您的示例中,这意味着为调用创建承诺requestAnimationFrame,然后将所有承诺与Promise.all返回一个承诺,该承诺在您的内部函数完成其任务时解决:

function inner() {
  return Promise.all([
    new Promise(...),
    new Promise(...),
    new Promise(...),
    new Promise(resolve => {
      requestAnimationFrame(() => {
        ...
        resolve();
      })
    }),
    new Promise(resolve => {
      requestAnimationFrame(() => {
        ...
        resolve();
      })
    }),
  ]);
}

(免责声明:以上不是很好的承诺代码——你不应该new Promise经常使用,只能在包装特定异步调用但不做任何其他事情的辅助函数中使用——但应该让你了解如何在这里使用承诺)


推荐阅读