我在JavaScript承诺方面遇到了一些问题。这是我的代码:
receiptID
我添加了一些评论来解释我想要做的事情。现在的问题是我得到promise variable
并创建另一个console.log
并将其推入promise数组,.then()
会打印出结果。
然而,在我注释掉该行并尝试在{{1}}打印出结果后,打印出promise promise消息,但是没有来自数组的结果,也没有错误消息,这意味着异步执行没有正确完成。
任何想法如何解决这个问题?先谢谢!
答案 0 :(得分:1)
您的代码中没有任何东西在等待那些从属承诺。因为您没有从then
处理程序返回任何内容,所以当处理程序完成时,promise then
返回会立即得到解决。所以你正在等待第一级承诺(你进入promises
的那些承诺),而不是那些查询收据细节的承诺。
承诺的关键之一是then
会返回新的承诺;它是一个管道,其中每个then
(和catch
)处理程序都可以修改传递的内容。 then
(或catch
)返回的承诺将使用then
处理程序的返回值解析,如果它不是类似承诺(“可能”)的值,或者是奴隶承诺返回then
处理程序,如果它像承诺一样(“可以”)。
所以你应该从等待收据的then
处理程序中传播一些东西;可能是Promise.all
的结果。我将它分解为单独的函数(在至少两个:一个获得外层,无论是什么,一个获得该级别的收据)。
另请注意,没有理由在您的顶级明确创建新承诺。你已经拥有一个:来自once
的那个。
如果我了解您要正确执行的操作,我会在此重新组织一下,根据这些项目获取收据信息,然后进行一次调用以获取收据而不是按项目调用,并从收据中获取分支详细信息。见评论:
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);
}
});
这可以用箭头函数的简洁形式更简洁地写出来,但这有时会妨碍清晰。