使用Promise.all在数组中执行promise会破坏它们 [英] Executing promises in array with Promise.all breaks them

查看:123
本文介绍了使用Promise.all在数组中执行promise会破坏它们的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个userIds数组,我在getOrdersByUserId()中使用它来获取这些用户在特定月份下的订单:

I have an array of userIds that I use in getOrdersByUserId() to get the orders placed by these users for a specific month:

function getOrdersByUserId(userId, month = 4) {
    const apiService = new ApiService();

    return apiService.getOrdersList(`?OrderingUser=${userId}`)
        .then(orders => {
            const monthOrders = orders.filter(order => new Date(order.FromTime)
            .getMonth() === month);

            return monthOrders;
        });
}

这是ApiService中的getOrdersList():

Here's getOrdersList() in ApiService:

getOrdersList(queryString = '') {
    return httpsRequest.createRequest(this.URL.ordersList + queryString, {}, this.requestHeaders, 'GET')
        .then(result => JSON.parse(result).Records);
}

httpsRequest.createRequest返回一个使用API​​响应解析的承诺(I如有必要,也可以共享该代码)。

httpsRequest.createRequest returns a promise that resolves with the response from the API (I can share that code too if necessary).

当我用8个userIds测试getOrdersByUserId()时,我每次都得到正确的记录。当我将这些调用放入一个promise链并使用Promise.All()执行它们时,这会中断。我在这个答案的帮助下写了下面的代码:等待每个人内部承诺完成

When I test getOrdersByUserId() with 8 userIds I have, I get the correct records every time. Where this breaks is when I put these calls into a promise chain and execute them with Promise.All(). I wrote the below code with help from this answer: Wait for forEach with a promise inside to finish

const promises = userIds.map(userId => {
            return getOrdersByUserId(userId, month)
                .then(orders => {
                    return orders;
                });
        });

        Promise.all(promises).then(results => {
            console.log(results);
        }).catch(err => {
           console.log(err);
        });

使用8个userIds进行测试我得到此错误四到五次:

Testing with the 8 userIds I get this error four or five times:

(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): SyntaxError: Unexpected end of JSON input

经过大量的控制台日志记录后,当httpsRequest.createRequest()给出的结果为空字符串而不是来自API的JSON响应。那么为什么所有这些具有相同userIds的调用都会单独工作,但在promise链中执行时会中断?我该如何解决这个问题?

After a lot of console logging it seems that this error occurs when httpsRequest.createRequest() gives a result that is an empty string, instead of a JSON response from the API. So why would all of these calls with the same userIds work individually, but break when executed in a promise chain? How can I resolve this?

推荐答案

你有一个常见的误解:你没有执行承诺。 Promise.all 不会运行任何内容。承诺只是一种观察操作的方法,可以知道它何时完成以及它是否有效。

You have a common misunderstanding: You don't execute promises. Promise.all doesn't "run" anything. A promise is just a means of watching an operation to know when it's done and whether it worked or failed.

在您的情况下,操作由<$ c $启动c> apiService.getOrdersList ,一旦你调用它。

In your case, the operations are started by apiService.getOrdersList, as soon as you call it.

你所看到的暗示


  1. API服务不喜欢您同时发送8个请求(可能是速率限制),

  1. The API service doesn't like you sending it eight simultaneous requests (perhaps it rate-limits), and

来自API服务的promise使用无效JSON的值解析,而不是在它无法处理#1时拒绝(这是不幸的,它应该拒绝,而不是解析)。

The promise from the API service resolves with a value that isn't valid JSON rather than rejecting when it can't handle #1 (which is unfortunate, it should reject, not resolve).

使用 Promise.all 没有什么可以打破这些操作。但显然,并行运行其中八个操作。

Nothing about using Promise.all breaks these operations. But apparently, running eight of these operations in parallel breaks.

你可以连续运行它们(一个接一个):

You could run them in series (one after another):

userIds.reduce((p, userId, index) => {
    return p.then(results => {
        return getOrdersByUserId(userId, month)
         .then(orders => {
             results[index] = orders;
             return results;
         });
    });
}, Promise.resolve([]))
.then(results => {
    // `results` is an array of results, in the same order as `userIds`
})
.catch(err => {
   console.log(err);
});

每次拨打 getOrdersByUserId 等待之前的一个完成;最终结果是与 userIds 数组的顺序相同的结果数组。

Each call to getOrdersByUserId waits for the previous one to complete; the final result is an array of results in the same order as the userIds array.

这篇关于使用Promise.all在数组中执行promise会破坏它们的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆