我对JavaScript的承诺有些问题。下面是我的代码:
//removed code我添加了一些注释来解释我正在尝试做的事情。现在的问题是,我获取了receiptID并创建了另一个promise variable,并将其推送到promise数组中,那里的console.log正在打印结果。
但是,在我注释掉该行并尝试在.then()中打印结果后,promise done消息被打印出来,但是没有来自数组的结果,也没有错误消息,这意味着异步执行没有正确完成。
有什么办法解决这个问题吗?在进阶时谢谢!
发布于 2017-08-01 18:54:02
您的代码中没有任何东西等待这些从属承诺。因为您没有从then处理程序返回任何内容,所以当您的处理程序完成时,then返回的承诺将立即实现。因此,您等待的是第一级承诺(放入promises中的承诺),而不是查询接收详细信息的承诺。
关于promise的一个关键问题是,then返回一个新的promise;它是一个管道,每个then (和catch)处理程序都可以在其中修改传递的内容。由then (或catch)返回的promise将使用then处理程序的返回值来实现,如果它不是类似promise ("thenable")的值,则将被解析为then处理程序的返回值,这意味着它将根据其他promise所做的事情来实现或拒绝。(仅供参考,我在我的博客上的中进入了promise术语-“履行”与“解决”,等等。)
因此,您应该从等待接收的then处理程序中传播一些内容;可能是Promise.all的结果。我会通过将其分解为单独的函数来实现(至少在two中:一个获取外层,不管它是什么,另一个获取该层的收据)。
还要注意,没有理由在您的顶层显式地创建新的promise。您已经有了一个:来自once的那个。
如果我理解正确的话,我在这里重新组织了一下,根据项目获取收据信息,然后调用one来获取收据,而不是调用每个项目,并从收据中获取分支详细信息。请参阅评论:
const promiseDataList =
// Get all receipt items for the category
firebase.database().ref('receiptItemIDsByCategory').child(category).once('value').then(itemIds => {
// Build a map of receipt info keyed by receipt ID by getting all of the items and, as
// we get them, storing the receipt info in the map
const receiptMap = new Map();
return Promise.all(itemIds.map(itemSnapshot => {
// Get the details of each receipt into a map keyed by receipt ID; since a receipt
// can have multiple items, be sure to check the map before adding a new entry
return firebase.database().ref('receiptItems').child(itemSnapshot.key).once('value').then(item => {
const itemDetail = item.val();
const price = itemDetail.price;
const quantity = itemDetail.quantity;
const itemTotal = price * quantity;
const receiptEntry = receiptMap.get(itemDetail.receiptID);
if (receiptEntry) {
// We already have this receipt, add to its total
receiptEntry.total += itemTotal;
} else {
// New receipt
receiptMap.set(itemDetail.receiptID, {id: itemDetail.receiptID, total: itemTotal});
}
});
})).then(() => {
// We have the map of receipts we want info for; get all receipts so we can filter
// for only the ones we want. (Note: Surely we could use the keys from receiptMap to
// limit this Firebase query?)
return firebase.database().ref('receipts').once('value').then(receipts => {
// Filter out the irrelevant receipts (again, Firebase perhaps could do that for us?)
// and then map the remaining ones to objects with the desired information
return receipts.filter(receipt => receiptMap.has(receipt.key)).map(receipt => {
const branchDetail = receipt.val().branch;
const branchName = branchDetail.branchName;
const branchAddress = branchDetail.branchAddress;
console.log(branchName + ' ' + branchAddress + ' ' + receipt.total);
return {branchName, branchAddress, total: receipt.total};
});
});
});
});
promiseDataList.then(arr => {
console.log('promise done');
for (var i = 0; i < arr.length; i++) {
console.log(arr[i].branchName + ' ' + arr[i].branchAddress + ' ' + arr[i].total);
}
});这可以用箭头函数的简明形式编写得更简洁一些,但这有时会妨碍清晰。
https://stackoverflow.com/questions/45435530
复制相似问题