我不确定是否有人真的对何时使用Promise.all()
(以及何时不使用)给出了最通用的解释:
什么是使用 promise.all() 的正确场景
Promise.all()
当您有多个Promise并且您的代码想知道这些Promise所代表的所有操作何时成功完成时,这非常有用。各个异步操作是什么并不重要。如果它们是异步的,由 promise 表示,并且您的代码想知道它们何时都成功完成,那么Promise.all()
构建就是为了做到这一点。
例如,假设您需要从三个单独的远程 API 调用中收集信息,并且当您获得所有三个 API 调用的结果时,您就需要使用所有三个结果运行一些进一步的代码。这种情况将是完美的Promise.all()
。你可以这样:
Promise.all([apiRequest(...), apiRequest(...), apiRequest(...)]).then(function(results) {
// API results in the results array here
// processing can continue using the results of all three API requests
}, function(err) {
// an error occurred, process the error here
});
Promise.all()
可能最常用于类似类型的请求(如上例所示),但没有理由需要它。如果你有一个不同的情况,你需要发出一个远程 API 请求,读取一个本地文件并读取一个本地温度探测器,然后当你有来自所有三个异步操作的数据时,你想要对所有数据进行一些处理三,你会再次使用Promise.all()
:
Promise.all([apiRequest(...), fs.promises.readFile(...), readTemperature(...)]).then(function(results) {
// all results in the results array here
// processing can continue using the results of all three async operations
}, function(err) {
// an error occurred, process the error here
});
另一方面,如果您不需要在它们之间进行协调并且可以单独处理每个异步操作,那么您不需要Promise.all()
. 您可以使用自己的.then()
处理程序触发每个单独的异步操作,并且不需要它们之间的协调。
此外Promise.all()
还有所谓的“快速失败”实现。它返回一个主Promise,一旦您通过它的第一个Promise被拒绝,它就会拒绝,或者当所有Promise都已解决时它将解决。因此,使用Promise.all()
这种类型的实现需要适合您的情况。在其他情况下,您想要运行多个异步操作并且您需要所有结果,即使其中一些失败。 Promise.all()
不会直接为你做那件事。相反,您可能会Promise.settle()
在这种情况下使用类似的东西。你可以看到这里的实现.settle()
这使您可以访问所有结果,即使有些结果失败。当您预计某些操作可能会失败并且您有一项有用的任务需要使用任何成功操作的结果时,或者您想检查所有未能基于此做出决策的操作的失败原因时,这尤其有用。
是否有使用 promise.all() 的最佳实践?只有当所有的Promise对象都是相同或相似的类型时才应该理想地使用它吗?
如上所述,单独的异步操作是什么或者它们是否是相同的类型并不重要。重要的是您的代码是否需要协调它们并知道它们何时全部成功。
列出一些您不会使用的情况也很有用Promise.all()
:
- 当您只有一个异步操作时。只需一个操作,您就可以
.then()
在一个 promise 上使用处理程序,而没有理由使用Promise.all()
.
- 当您不需要在多个异步操作之间进行协调时。
- 当快速失败实施不合适时。如果您需要所有结果,即使有些结果失败,那么
Promise.all()
它本身也不会这样做。你可能想要类似的东西Promise.allSettled()
。
- 如果您的异步操作未全部返回Promise,
Promise.all()
则无法跟踪未通过Promise管理的异步操作。