Javascript 何时使用 promise.all()?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38180080/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:09:51  来源:igfitidea点击:

When to use promise.all()?

javascriptdesign-patternspromise

提问by nikjohn

This is more of a conceptual question. I understand the Promise design pattern, but couldn't find a reliable source to answer my question about promise.all():

这更像是一个概念性问题。我了解 Promise 设计模式,但找不到可靠的来源来回答我的以下问题promise.all()

What is(are) the correct scenario(s) to use promise.all()

什么是(是)使用的正确场景 promise.all()

OR

或者

Are there any best practices to use promise.all()? Should it be ideally used only if all of the promise objects are of the same or similar types?

是否有任何最佳做法可供使用promise.all()?只有当所有的承诺对象都是相同或相似的类型时才应该理想地使用它吗?

The only one I could think of is:

我唯一能想到的就是:

  • Use promise.all()if you want to resolve the promise onlyif allof the promise objects resolve and reject if even one rejects.
  • promise.all()如果您只想在所有承诺对象都解决并拒绝甚至一个拒绝时才解决承诺,请使用。

回答by jfriend00

I'm not sure anyone has really given the most general purpose explanation for when to use Promise.all()(and when not to use it):

我不确定是否有人真的就何时使用Promise.all()(以及何时不使用)给出了最通用的解释:

What is(are) the correct scenario(s) to use promise.all()

什么是使用 promise.all() 的正确场景

Promise.all()is useful anytime you have more than one promise and your code wants to know when all the operations that those promises represent have finished successfully. It does not matter what the individual async operations are. If they are async, are represented by promises and your code wants to know when they have all completed, then Promise.all()is built to do exactly that.

Promise.all()当您有多个承诺并且您的代码想知道这些承诺所代表的所有操作何时成功完成时,这很有用。各个异步操作是什么并不重要。如果它们是异步的,由 Promise 表示,并且您的代码想知道它们何时全部完成,那么Promise.all()构建就是为了做到这一点。

For example, suppose you need to gather information from three separate remote API calls and when you have the results from all three API calls, you then need to run some further code using all three results. That situation would be perfect for Promise.all(). You could so something like this:

例如,假设您需要从三个单独的远程 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()is probably most commonly used with similar types of requests (as in the above example), but there is no reason that it needs to be. If you had a different case where you needed to make a remote API request, read a local file and read a local temperature probe and then when you had data from all three async operations, you wanted to then do some processing with the data from all three, you would again use Promise.all():

Promise.all()可能最常用于类似类型的请求(如上例所示),但没有理由需要它。如果你有一个不同的情况,你需要发出一个远程 API 请求,读取一个本地文件并读取一个本地温度探测器,然后当你有来自所有三个异步操作的数据时,你想要对所有数据进行一些处理三,你会再次使用Promise.all()

Promise.all([apiRequest(...), fs.readFileAsync(...), 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
});

On the flip side, if you don't need to coordinate among them and can just handle each async operation individually, then you don't need Promise.all(). You can just fire each of your separate async operations with their own .then()handlers and no coordination between them is needed.

另一方面,如果您不需要在它们之间进行协调并且可以单独处理每个异步操作,那么您不需要Promise.all(). 您可以使用自己的.then()处理程序触发每个单独的异步操作,并且不需要它们之间的协调。

In addition Promise.all()has what is called a "fast fail" implementation. It returns a master promise that will reject as soon as the first promise you passed it rejects or it will resolve when all the promises have resolved. So, to use Promise.all()that type of implementation needs to work for your situation. There are other situations where you want to run multiple async operations and you need all the results, even if some of them failed. Promise.all()will not do that for you directly. Instead, you would likely use something like Promise.settle()for that situation. You can see an implementation of .settle()herewhich gives you access to all the results, even if some failed. This is particularly useful when you expect that some operations might fail and you have a useful task to pursue with the results from whatever operations succeeded or you want to examine the failure reasons for all the operations that failed to make decisions based on that.

此外Promise.all()还有所谓的“快速失败”实现。它返回一个主承诺,一旦您通过它的第一个承诺被拒绝,它就会拒绝,或者当所有承诺都已解决时它将解决。因此,使用Promise.all()这种类型的实现需要适合您的情况。在其他情况下,您想要运行多个异步操作并且您需要所有结果,即使其中一些结果失败。 Promise.all()不会直接为你做那件事。相反,您可能会Promise.settle()在这种情况下使用类似的东西。你可以看到这里的实现.settle()这使您可以访问所有结果,即使有些结果失败。当您预计某些操作可能会失败并且您有一项有用的任务需要使用任何成功操作的结果时,或者您想检查所有未能基于此做出决策的操作的失败原因时,这尤其有用。

Are there any best practices to use promise.all()? Should it be ideally used only if all of the promise objects are of the same or similar types?

是否有使用 promise.all() 的最佳实践?只有当所有承诺对象都是相同或相似的类型时才应该理想地使用它吗?

As explained above, it does not matter what the individual async operations are or if they are the same type. It only matters whether your code needs to coordinate them and know when they all succeed.

如上所述,单独的异步操作是什么或者它们是否是相同的类型并不重要。重要的是您的代码是否需要协调它们并知道它们何时全部成功。



It's also useful to list some situations when you would notuse Promise.all():

列出一些您不会使用的情况也很有用Promise.all()

  1. When you only have one async operation. With only one operation, you can just use a .then()handler on the one promise and there is no reason for Promise.all().
  2. When you don't need to coordinate among multiple async operations.
  3. When a fast fail implementation is not appropriate. If you need all results, even if some fail, then Promise.all()will not do that by itself. You will probably want something like Promise.settle()instead.
  4. If your async operations do not all return promises, Promise.all()cannot track an async operation that is not managed through a promise.
  1. 当您只有一个异步操作时。只需一个操作,您就可以.then()在一个 promise 上使用处理程序,而没有理由使用Promise.all().
  2. 当您不需要在多个异步操作之间进行协调时。
  3. 当快速失败实施不合适时。如果您需要所有结果,即使有些结果失败,那么Promise.all()它本身也不会这样做。你可能会想要类似的东西Promise.settle()
  4. 如果您的异步操作未全部返回承诺,Promise.all()则无法跟踪未通过承诺管理的异步操作。

回答by joews

Promise.allis for waiting for several Promises to resolve in parallel (at the same time). It returns a Promise that resolves when all of the input Promises have resolved:

Promise.all用于等待多个 Promise 并行(同时)解决。当所有输入 Promise 都已解决时,它会返回一个已解决的 Promise:

// p1, p2, p3 are Promises
Promise.all([p1, p2, p3])
  .then(([p1Result, p2Result, p3Result]) => {
    // This function is called when p1, p2 and p3 have all resolved.
    // The arguments are the resolved values.
  })

If anyof the input Promises is rejected, the Promise returned by Promise.allis also rejected.

如果任何输入 Promise 被拒绝,则返回的 PromisePromise.all也会被拒绝。

A common scenario is waiting for several API requests to finish so you can combine their results:

一个常见的场景是等待多个 API 请求完成,以便您可以合并它们的结果:

 const contentPromise = requestUser();
 const commentsPromise = requestComments();

 const combinedContent = Promise.all([contentPromise, commentsPromise])
   .then(([content, comments]) => {
     // content and comments have both finished loading.
   })

You can use Promise.allwith Promiseinstance.

您可以Promise.allPromise实例一起使用。

回答by sdgluck

It's hard to answer these questions as they are the type that tend to answer themselves as one uses the available APIs of a language feature. Basically, it's fine to use Promises any way that suits your use case, so long as you avoid their anti-patterns.

很难回答这些问题,因为当人们使用语言功能的可用 API 时,这些问题往往会自行回答。基本上,只要您避免使用 Promise 的反模式,就可以以任何适合您的用例的方式使用 Promise 。

What is(are) the correct scenario(s) to use promise.all()

什么是使用 promise.all() 的正确场景

Any situation in which an operation depends on the successful resolution of multiple promises.

操作取决于多个承诺的成功解决的任何情况。

Are there any best practices to use promise.all()? Should it be ideally used only if all of the promise objects are of the same or similar types?

是否有使用 promise.all() 的最佳实践?只有当所有承诺对象都是相同或相似的类型时才应该理想地使用它吗?

Generally, no and no.

一般来说,没有和没有。

回答by miquelarranz

I use promise.all()when I have to do some requests to my API and I don't want to display something before the application loads all the data requested, so I delay the execution flow until I have all the data I need.

我用promise.all()的时候我必须做一些要求我的API,我不希望加载应用程序的所有数据请求之前显示的东西,所以我推迟执行流程,直到我有我需要的所有数据。

Example:

例子:

What I want to doI want to load the users of my app and their products (imagine that you have to do multiple requests) before displaying a table in my app with the user emails and the product names of each user.

我想要做什么 我想在我的应用程序中显示包含用户电子邮件和每个用户的产品名称的表格之前加载我的应用程序及其产品的用户(假设您必须执行多个请求)。

What I do nextI send the requests to my API creating the promises and using promise.all()

接下来我要做的是将请求发送到我的 API 创建承诺并使用promise.all()

What I do when all the data has been loadedOnce the data arrives to my app, I can execute the callback of promises.all()and then make visible the table with the users.

加载所有数据后我要做的事情一旦数据到达我的应用程序,我就可以执行 的回调,promises.all()然后让用户看到该表。

I hope it helps you to see in which scenario makes sense to use promises.all()

我希望它可以帮助您了解在哪种情况下使用有意义 promises.all()

回答by Nancy thakkar

Promise.all-This method is useful for when you want to wait for more than one promise to complete or The Promise.all(iterable) method returns a promise that resolves when all of the promises in the iterable argument have resolved, or rejects with the reason of the first passed promise that rejects.

Promise.all-当您想要等待多个承诺完成或 Promise.all(iterable) 方法返回一个承诺时,该承诺会在 iterable 参数中的所有承诺都已解决时解决,或拒绝与第一个通过的承诺拒绝的原因。

2.Just use Promise.all(files).catch(err => { }) This throws an error if ANY of the promises are rejected.

2.Just use Promise.all(files).catch(err => { }) 如果任何承诺被拒绝,这将引发错误。

3.Use .reflect on the promises before .all if you want to wait for all promises to reject or fulfill

3.如果你想等待所有的promise被拒绝或履行,在.all之前的promise上使用.reflect

  1. Syntax -Promise.all(iterable);
  1. 语法 -Promise.all(iterable);

回答by Callum Linington

I tend to use promise all for something like this:

我倾向于将 promise all 用于这样的事情:

myService.getUsers()
   .then(users => {
       this.users = users;

       var profileRequests = users.map(user => {
           return myService.getProfile(user.Id); // returns a promise
       });

       return Promise.all(profileRequests);
   })
   .then(userProfilesRequest => {
       // do something here with all the user profiles, like assign them back to the users.

       this.users.forEach((user, index) => {
           user.profile = userProfilesRequest[index];
       });
   });

Here, for each user we're going off and getting their profile. I don't want my promise chain to get out of hand now that i have xamount of promises to resolve.

在这里,对于每个用户,我们将开始获取他们的个人资料。我不希望我的承诺链失控,因为我有x很多承诺要解决。

So Promise.all()will basically aggregate all my promises back into one, and I can manage that through the next then. I can keep doing this for as long as a like, say for each profile I want to get related settings etc. etc. Each time I create tonnes more promises, I can aggregate them all back into one.

所以Promise.all()基本上会将我所有的承诺汇总成一个,我可以通过下一个then. 我可以一直这样做,只要喜欢,比如说对于每个配置文件,我想获得相关设置等等。每次我创建更多的承诺时,我可以将它们全部聚合回一个。

回答by Venky

Promise.allpasses an array of values from all the promises in the iterable object that it was passed.

Promise.all从它被传递的可迭代对象中的所有承诺中传递一个值数组。

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

var isCallFailed = false;
function myEndpoint1() {
  return isCallFailed ? Promise.reject("Bohoo!") :Promise.resolve({"a":"a"});
}
function myEndpoint2() {
  return Promise.resolve({"b":"b"});
}

Promise.all([myEndpoint1(), myEndpoint2()])
.then(values => {
  var data1 = values[0];
  var data2 = values[1];
  alert("SUCCESS... data1: " + JSON.stringify(data1) + "; data2: " +  JSON.stringify(data2));
})
.catch(error => {
  alert("ERROR... " + error);
});

you can try another case by making isCallFailed = true.

您可以通过 make 尝试另一个案例isCallFailed = true

回答by Vanya Avchyan

If you are interested only Promise.all then read below Promise.all

如果你只对 Promise.all 感兴趣,那么请阅读下面的 Promise.all

Promise (usually they are called "Promise") - provide a convenient way to organize asynchronous code.

Promise(通常被称为“Promise”)——提供一种方便的方式来组织异步代码。

Promise - is a special object that contains your state. Initially, pending ( ?waiting"), and then - one of: fulfilled ( ?was successful") or rejected ( ?done with error").

Promise - 是一个包含你的状态的特殊对象。最初,pending (?waiting"),然后 - 以下之一:已完成(?was success")或拒绝(?done with error")。

On the promise to hang callbacks can be of two types:

关于挂起回调的承诺可以有两种类型:

  • unFulfilled - triggered when the promise in a state of "completed successfully."
  • Rejected - triggered when the promise in the "made in error."
  • unFulfilled - 当承诺处于“成功完成”状态时触发。
  • Rejected - 当承诺在“made in error”时触发。

The syntax for creating the Promise:

创建 Promise 的语法:

var promise = new Promise(function(resolve, reject) {
  // This function will be called automatically

  // It is possible to make any asynchronous operations,
  // And when they will end - you need to call one of:
  // resolve(result) on success
  // reject(error) on error
})

Universal method for hanging handlers:

悬挂处理程序的通用方法:

promise.then(onFulfilled, onRejected)
  • onFulfilled - a function that will be called with the result with resolve.

  • onRejected - a function that will be called when an error reject.

  • onFulfilled - 一个将使用解析结果调用的函数。

  • onRejected - 错误拒绝时将调用的函数。

With its help you can assign both the handler once, and only one:

在它的帮助下,您可以一次分配处理程序,并且只能分配一个:

// onFulfilled It works on success
promise.then(onFulfilled)
// onRejected It works on error
promise.then(null, onRejected)

Synchronous throw - the same that reject

同步抛出 - 与拒绝相同

'use strict';

let p = new Promise((resolve, reject) => {
  // то же что reject(new Error("o_O"))
  throw new Error("o_O");
});

p.catch(alert); // Error: o_O

PromisificationPromisification - When taking asynchronous functionality and make it a wrapper for returning PROMIS.

PromisificationPromisification - 当采用异步功能并使其成为返回 PROMIS 的包装器时。

After Promisification functional use often becomes much more convenient.

在 Promisification 之后,函数的使用通常会变得更加方便。

As an example, make a wrapper for using XMLHttpRequest requests

例如,为使用 XMLHttpRequest 请求制作一个包装器

httpGet function (url) will return PROMIS, which upon successful data loading with the url will go into fulfilled with these data, and in case of error - in rejected with an error information:

httpGet 函数 (url) 将返回 PROMIS,在使用 url 成功加载数据后,将使用这些数据实现,并且在出现错误时 - 以错误信息拒绝:

function httpGet(url) {

    return new Promise(function(resolve, reject) {

        var xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);

        xhr.onload = function() {
            if (this.status == 200) {
                resolve(this.response);
            } else {
                var error = new Error(this.statusText);
                error.code = this.status;
                reject(error);
            }
        };

        xhr.onerror = function() {
            reject(new Error("Network Error"));
        };

        xhr.send();
    });

}

As you can see, inside the function XMLHttpRequest object is created and sent as usual, when onload / onerror are called, respectively, resolve (at the status 200) or reject.

如您所见,在函数内部,XMLHttpRequest 对象像往常一样被创建和发送,当 onload/onerror 被调用时,分别是 resolve(在状态 200)或拒绝。

Using:

使用:

httpGet("/article/promise/user.json")
    .then(
        response => alert(`Fulfilled: ${response}`),
        error => alert(`Rejected: ${error}`)
    );

Parallel execution

并行执行

What if we want to implement multiple asynchronous processes simultaneously and to process their results?

如果我们想同时实现多个异步进程并处理它们的结果怎么办?

The Promise class has the following static methods.

Promise 类具有以下静态方法。

Promise.all(iterable)

Promise.all(可迭代)

Call Promise.all (iterable) receives an array (or other iterable object) and returns PROMIS PROMIS, which waits until all transferred PROMIS completed, and changes to the state "done" with an array of results.

调用 Promise.all(iterable) 接收一个数组(或其他可迭代对象)并返回 PROMIS PROMIS,它等待直到所有传输的 PROMIS 完成,并用数组结果更改为“done”状态。

For example:

例如:

Promise.all([
    httpGet('/article/promise/user.json'),
    httpGet('/article/promise/guest.json')
]).then(results => {
    alert(results);
});

Let's say we have an array of URL.

假设我们有一个 URL 数组。

let urls = [
  '/article/promise/user.json',
  '/article/promise/guest.json'
];

To download them in parallel, you need to:

要并行下载它们,您需要:

  1. Create for each URL corresponding to PROMIS.
  2. Wrap an array of PROMIS in Promise.all.
  1. 为每个对应于 PROMIS 的 URL 创建。
  2. 在 Promise.all 中包装一个 PROMIS 数组。

We obtain this:

我们得到这个:

'use strict';

'使用严格';

let urls = [
  '/article/promise/user.json',
  '/article/promise/guest.json'
];

Promise.all( urls.map(httpGet) )
  .then(results => {
    alert(results);
});

Note that if any of Promise ended with an error, the result will

请注意,如果任何 Promise 以错误结束,结果将

Promise.all this error.

Promise.all 这个错误。

At the same time the rest of PROMIS ignored.

同时PROMIS的其余部分忽略了。

For example:

例如:

Promise.all([
    httpGet('/article/promise/user.json'),
    httpGet('/article/promise/guest.json'),
    httpGet('/article/promise/no-such-page.json') // (нет такой страницы)
]).then(
    result => alert("не сработает"),
    error => alert("Ошибка: " + error.message) // Ошибка: Not Found
)

In total:

总共:

  • Promise - is a special object that stores its state, the current result (if any), and callbacks.
  • When you create a new Promise ((resolve, reject) => ...) function argument starts automatically, which should call resolve (result) on success, and reject (error) - error.
  • Argument resolve / reject (only the first, and the rest are ignored) is passed to handlers on this Promise.
  • Handlers are appointed by calling .then / catch.
  • To transfer the results from one processor to another using Channing.
  • Promise - 是一个特殊的对象,用于存储其状态、当前结果(如果有)和回调。
  • 当你创建一个新的 Promise ((resolve, reject) => ...) 函数参数时,它会自动启动,它应该在成功时调用 resolve (result),而reject (error) - 错误。
  • 参数解析/拒绝(仅第一个,其余被忽略)传递给此 Promise 的处理程序。
  • 处理程序通过调用 .then/catch 来指定。
  • 使用 Channing 将结果从一个处理器传输到另一个处理器。

https://www.promisejs.org/patterns/

https://www.promisejs.org/patterns/