【问题标题】:Executing promises in array with Promise.all breaks them使用 Promise.all 在数组中执行承诺会破坏它们
【发布时间】:2018-11-29 17:34:36
【问题描述】:

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

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():

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

httpsRequest.createRequest 返回一个通过 API 响应解决的承诺(如果需要,我也可以共享该代码)。

当我用我拥有的 8 个用户 ID 测试 getOrdersByUserId() 时,我每次都得到正确的记录。当我将这些调用放入 Promise 链并使用 Promise.All() 执行它们时,就会中断。我在这个答案的帮助下编写了以下代码: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 个用户 ID 进行测试我得到了四五次这个错误:

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

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

【问题讨论】:

    标签: javascript ecmascript-6 promise


    【解决方案1】:

    你有一个常见的误解:你没有执行承诺。 Promise.all 不会“运行”任何东西。 Promise 只是一种观察操作以了解操作何时完成以及它是否成功或失败的方法。

    在您的情况下,操作由apiService.getOrdersList 启动,只要您调用它。

    你所看到的表明

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

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

    使用Promise.all 不会破坏这些操作。但显然,并行中断运行其中的 8 个操作。

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

    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 数组顺序相同的结果数组。

    【讨论】:

    • 非常感谢您的周到回复!但是,运行此程序时出现错误,“ReferenceError: p is not defined”。你知道是什么原因造成的吗?
    • @no_parachute44 - 抱歉,打错了。应该是acc.p = acc.p.then...
    • 好的,现在我得到“userIds.reduce(...).then 不是函数”以及我的问题中首先提到的五个错误。
    • @no_parachute44 - 抱歉,记错了模式。固定在上面(希望)。
    • TJ,你是男人中的神!非常感谢你,我无法告诉你这对我有多大帮助。希望你有一个美好的一天:)
    猜你喜欢
    • 2017-05-17
    • 2016-11-25
    • 2020-10-03
    • 1970-01-01
    • 2016-11-07
    • 2018-04-07
    • 1970-01-01
    • 2019-02-27
    • 1970-01-01
    相关资源
    最近更新 更多