У меня возникла проблема с обещаниями JavaScript. Вот мой код:
//removed code
Я добавил несколько комментариев, чтобы объяснить, что я пытаюсь сделать. Проблема теперь в точке, где я получаю receiptID
и создал другую promise variable
и receiptID
ее в массив обещаний, console.log
выводит результат.
Однако после того, как я прокомментировал эту строку и попытался распечатать результат в .then()
, сообщение с обещанием было распечатано, но результат не получен из массива или сообщение об ошибке, что означает, что асинхронное выполнение не выполняется должным образом.
Любые идеи, как это исправить? Заранее спасибо!
Ничто в коде не ждет этих подчиненных обещаний. Потому что вы ничего из вашего не возвращает then
обработчик, обещание then
возвращается немедленно решена, когда завершает обработчик. Итак, вы ждете обещаний первого уровня (те, которые вы вставляете в promises
), но не те, которые запрашивают информацию о получении.
Одна из ключевых моментов в обещаниях - это then
что дает новое обещание; это трубопровод, где каждый then
(и catch
обработчик) может изменить то, что проездом. Обещание, возвращенное к тому then
(или catch
), будет разрешено с возвращаемым значением обработчика then
, если это не похожее на обещание ("thenable") значение или slav, обещающее возврат обработчика then
если он обещает -подобный ("thenable").
Таким образом, вы должны распространять что - то из вашего 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);
}
});
Это может быть написано немного более кратко с краткой формой функций стрелок, но это может иногда мешать ясности.
var itemData = snapshot.val(); var itemKey = snapshot.key;
и тому подобное. firebase...once()
будет частью query
. Если вы не знакомы с обещаниями, я настоятельно рекомендую сначала проработать несколько более простых сценариев и подготовиться к этой задаче.
Promise
конструктора антипаттерна !