NodeJS中的嵌套promise

我在NodeJS中编写一个服务,它检索一个Items列表。 对于每一个,我必须创build一个计数器,指示可用项目的数量。 所以,如果商品出现在商店里,柜台只是增加和解决承诺(因为我相信最多只有一个库存)。

否则,如果在库存中,我必须检查可用件的确切数量。

如果它不是以前的两个案例之一,我会解决承诺,然后转到下一个项目。

问题在于第二种情况,因为在解决(当前项目的)主要承诺之前,我必须等待调用来检索仓库中的零件计数器。 由于它是一个asynchronous代码,当它进入第二个“else”时,它会触发库存中的计件器的调用,并立即parsing承诺,而不用等待调用结束。 我怎样才能解决这个承诺的连接?

这是代码:

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); 

请记住,您可以通过thencatch创build承诺 ,其中每个处理程序都会转换分辨率值。 既然你的act()明显地返回了一个承诺,那么你的代码根本就不需要new Promise 。 相反,只是使用链。

如果产品存在,则需要进行子查询的事实不成问题; then (和catch )总是返回承诺,所以如果你从你的callback中返回一个简单的值,那么他们创造的承诺就会用这个价值来解决,但是如果你返回一个承诺,那么他们创造的承诺就是从属于承诺的。

下面是基于问题代码的一个简图:

 // 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` }); }));