我在getOrdersByUserId()中使用了一组userId,以获取这些用户在特定月份下的订单:
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个userId进行测试时,出现四到五次此错误:
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): SyntaxError: Unexpected end of JSON input
大量控制台记录后,当httpsRequest.createRequest()给出的结果为空字符串而不是来自API的JSON响应时,似乎会发生此错误。那么,为什么所有这些具有相同userId的调用都可以单独工作,但是在promise链中执行时却中断了呢?我该如何解决?
答案 0 :(得分:2)
您有一个常见的误解:您不执行承诺。 Promise.all
不会“运行”任何内容。许诺只是一种观察操作以了解何时完成以及它是否起作用的方法。
在您的情况下,操作一经调用apiService.getOrdersList
就开始。
您所看到的暗示
API服务不喜欢您同时发送八个请求(也许是速率限制),并且
API服务的承诺将使用无效的JSON值进行解析,而不是在无法处理#1时拒绝(这很不幸,它应该拒绝而不是解析)。
使用Promise.all
不会破坏这些操作。但显然,并行运行这些操作中的八个。
您可以连续运行它们(一个接一个):
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
数组相同。