代碼中沒有任何內容正在等待這些從屬承諾。因爲您沒有從您的處理程序中返回任何內容,所以您的處理程序完成後,立即解析承諾then
返回。因此,您正在等待第一級承諾(您推入promises
的承諾),但不是那些查詢收據詳細信息的承諾。
承諾的關鍵之一是then
返回新的承諾;這是一個管道,其中每一個then
(和catch
)處理程序可以修改什麼穿過。由then
(或catch
)返回的承諾將使用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);
}
});
這可能是有點更簡明地寫有箭頭的功能簡潔的形式,但可以在清晰的方式有時會。
的可能的複製[爲什麼在。那麼()鏈接未定義的價值承諾?(https://stackoverflow.com/questions/44439596/why-is-value-undefined-at-then-chained-to-諾) –
避免['Promise'構造反模式](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi
我想'innerResult.entries'會失敗 –