我正在NodeJS中编写一个服务,它检索一个Items列表。对于每一个,我必须创建一个指示可用项目数量的计数器。 因此,如果商品存在于商店中,则计数器只会递增并解析承诺(因为我确定最多只有一个库存)。
否则,如果它在库存中,我必须检查可用件的确切数量。
如果它不是前两个案例之一,我将解决这个承诺,然后转到下一个项目。
问题出在第二种情况,因为在解决主要承诺(当前项目)之前,我必须等待调用才能检索仓库中的零件计数器结束。由于它是一个异步代码,当它当前进入第二个“else”时,它会触发对股票中的计件器的调用,并立即解析承诺,而不等待调用结束。 我怎样才能解决这种承诺的连接?
这是代码:
let promises: any[] = [];
for (let i = 0, itemsLength = itemList.length; i < itemsLength; i++) {
let currentItem = itemList[i];
promises.push(
new Promise(function(resolve: Function, reject: Function) {
act({
...call the service to retrieve the item list
})
.then(function(senecaResponse: SenecaResponse < any > ) {
if (senecaResponse && senecaResponse.error) {
reject(new Error(senecaResponse.error));
}
currentItem.itemDetails = senecaResponse.response;
currentItem.counters = {
available: 0
};
if (currentItem.itemDetails && currentItem.itemDetails.length) {
for (let k = 0, detailsLength = currentItem.itemDetails.length; k < detailsLength; k++) {
let currentItemDetail = currentItem.itemDetails[k];
if (currentItemDetail.val === "IN_THE_STORE") {
currentItem.counters.available++;
resolve();
} else if (currentItemDetail.courseType === "IN_STOCK") {
act({
...call the service to retrieve the counter in stock
})
.then(function(stockResponse: SenecaResponse < any > ) {
if (stockResponse && stockResponse.error) {
reject(new Error(stockResponse.error));
} else {
currentItem.counters.available = stockResponse.response;
}
resolve();
})
.catch(function(error: Error) {
options.logger.error(error);
reject(error);
})
} else {
resolve();
}
}
} else {
resolve();
}
})
.catch(function(error: Error) {
options.logger.error(error);
reject(error);
})
})
);
}
return Promise.all(promises);
答案 0 :(得分:0)
请记住,您可以通过then
和catch
创建承诺的链,其中每个处理程序一路转换分辨率值。由于您的act()
显然会返回一个承诺,因此您的代码中根本不需要new Promise
。相反,只需使用链。
如果产品存在,您需要进行子查询这一事实不是问题; then
(和catch
)总是返回promises,所以如果你从回调函数中返回一个简单的值,那么他们创建的promise将使用该值解析,但是如果你返回一个promise,那么他们创建的promise就是slaved对那个承诺。
以下是根据问题中的代码如何执行此操作的草图:
// Result is a promise for an array of populated items
return Promise.all(itemList.map(currentItem => {
act(/*...query using `currentItem`...*/)
.then(senecaResponse => {
if (!senecaResponse || senecaResponse.error) {
// Does this really happen? It should reject rather than resolving with something invalid.
throw new Error((senecaResponse && senecaResponse.error) || "Invalid response");
}
currentItem.itemDetails = senecaResponse.response;
currentItem.counters = {
available: 0
};
return Promise.all((currentItem.itemDetails || []).map(currentItemDetail => {
if (currentItemDetail.courseType === "IN_STOCK") {
return act(/*...query using `currentItemDetail`...*/).then(stockResponse => {
currentItem.counters.available = stockResponse.response;
});
}
if (currentItemDetail.val === "IN_THE_STORE") {
currentItem.counters.available++;
}
// (We don't care what value we return, so the default `undefined` is fine; we
// don't use the array from `Promise.all`
}))
.then(() => currentItem); // <== Note that this means we convert the array `Promise.all`
// resolves with back into just the `currentItem`
});
}));