- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在使用 JavaScript promises 时遇到了一些问题。这是我的代码:
let promiseDataList = new Promise((resolve, reject) => {
// first query to get list of all receipt items under certain category
var query = firebase.database().ref('receiptItemIDsByCategory').child(category);
query.once( 'value', data => {
// promises array
var promises = [];
// loop through each and get the key for each receipt items
data.forEach(snapshot => {
var itemData = snapshot.val();
// get key here
var itemKey = snapshot.key;
// second query to get the details of each receipt items based on the receipt item key
var query = firebase.database().ref('receiptItems').child(itemKey);
var promise = query.once('value');
promises.push(promise);
promise.then(data => {
// get receipt item details based on the item key
var itemDetail = data.val();
var price = itemDetail.price;
var quantity = itemDetail.quantity;
var itemTotal = price * quantity;
var receiptID = itemDetail.receiptID;
// get branch details based on receipt ID
var query = firebase.database().ref('receipts');
var promise1 = query.once('value');
// add promise to array
promises.push(promise1);
// find matching receiptID then get its branch details
promise1.then(data => {
data.forEach(snapshot => {
snapshot.forEach(childSnapshot => {
if(childSnapshot.key == receiptID){
var branchDetail = childSnapshot.val().branch;
var branchName = branchDetail.branchName;
var branchAddress = branchDetail.branchAddress;
console.log(branchName + ' ' + branchAddress + ' ' + itemTotal);
// push data into the final array to be used in some other parts
datasetarr.push({branchName: branchName, branchAddress: branchAddress, total: itemTotal});
}
});
});
});
});
});
// wait till all promises are finished then resolve the result array
Promise.all(promises).then(() => resolve(datasetarr));
});
});
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);
}
});
我添加了一些评论来解释我正在尝试做的事情。现在的问题是在我获得 receiptID
并创建另一个 promise 变量
并将其插入 promise 数组,console.log
时正在打印结果。
但是,在我注释掉该行并尝试在 .then()
中打印结果后,打印了 promise done 消息,但数组没有结果,也没有错误消息,这意味着异步执行没有正确完成。
有什么办法解决这个问题吗?
最佳答案
您的代码中没有任何内容正在等待那些从属 promise 。因为您没有从您的 then
处理程序返回任何内容,所以 then
返回的 promise 会在您的处理程序完成时立即实现。因此,您正在等待第一级 promise (您推送到 promises
中的 promise ),而不是查询收据详细信息的 promise 。
关于 promise 的一个关键点是 then
返回一个新的 promise;这是一个管道,其中每个then
(和catch
)处理程序都可以修改通过的内容。 then
(或 catch
)返回的 promise 将由 then
处理程序的返回值实现,如果它不是类似 promise 的 ( "thenable") 值,或者将被解析为 then
处理程序的返回,如果它是 promise-like("thenable"),意味着它将被履行或拒绝基于其他 promise 的作用。 (FWIW,我在我的博客上的 this post 中介绍了 promise 术语——“fulfill”与“resolve”等。)
因此,您应该从等待收据的 then
处理程序传播一些内容;可能是 Promise.all
的结果。我会通过将其分解为单独的函数来做到这一点(至少两个:一个获取外层,不管它是什么,另一个获取该层的收据)。
另请注意,没有理由在您的顶层显式创建新 promise 。您已经有了一个:来自 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);
}
});
这可以用箭头函数的简洁形式写得更简洁一些,但这有时会妨碍清晰度。
关于JavaScript 多重 promise 导致 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45435530/
如何从 promise 中退出 promise ? perl6 文档没有提供简单的方法。例如: my $x = start { loop { # loop forever until "qui
我的用户 Controller 中有一个索引操作,其中我试图连续做两件事,并且在它们都有机会完成之前不执行所需的 res.json() 方法。 我有一个加入用户的友谊加入模型。一列是 friender
请帮我解释一下为什么日志结果有两种不同: 方式 1:每 1 秒顺序记录一次 方式 2:1 秒后记录所有元素。 // Way 1 let sequence = Promise.resolve(); [1
我的问题很简单。 Promise.all() 方法可以返回 Promise 吗?让我解释一下: function simpleFunction() { let queue = [];
我正在使用 Promise 从存储中读取文件并转换为 base64 字符串。我有图像数组,使用 RNFS 读取图像 const promise_Images = _Images.map(async (
如果使用非空数组调用 Promise.all 或 Promise.race,它们将返回一个待处理的 Promise: console.log(Promise.all([1])); // prints
Promise.all 是否可以在没有包装 promise 的情况下返回链的最后一个值? 如果不使用 await,它在我的上下文中不起作用 没有包装的例子: function sum1(x){ r
我一直在玩 promise,通常能想出如何处理好它们,但在这种情况下,我不知道如何删除一个 promise-wrapping level。 代码如下: let promise2 = promise1.
考虑以下嵌套的Promises结构: const getData = async() => { const refs = [{ name: "John33", age: 3
我已经阅读了 Promise/A+ 规范,但据我了解,还有诸如 Promise/A 和 Promise 之类的东西。它们之间有什么区别? Promise 和 Promise/A 规范也是如此吗?如果是
当我运行以下代码时: my $timer = Promise.in(2); my $after = $timer.then({ say "2 seconds are over!"; 'result'
以下简单的 promise 是发誓的,我不允许打破它。 my $my_promise = start { loop {} # or sleep x; 'promise re
我正在尝试扩展Promise: class PersistedPromise extends Promise { } 然后在派生类上调用静态resolve以直接创建一个已解决的Promise: Per
我有两个返回 promise 的函数,我独立使用它们作为: getLocal().then(...) 和 getWeb().then(...) 但是现在我遇到了一个奇怪的问题: 1) 我需要第三个
我不知道 promise.all 解决方案中的 promise.all 是否是一个好的实践。我不确定。 我需要从一组用户获取信息,然后通过此信息响应,我需要发送消息通知。 let userList =
我一直在尝试使用 queueMicrotask() 函数,但我没有弄清楚当回调是微任务时回调的优先级如何。查看以下代码: function tasksAndMicroTasks() { const
我一直在尝试使用 queueMicrotask() 函数,但我没有弄清楚当回调是微任务时回调的优先级如何。查看以下代码: function tasksAndMicroTasks() { const
今年早些时候,我在 Pharo Smalltalk 参与了一个 promise 项目。这个想法是为了实现以下行为: ([ 30 seconds wait. 4 ]promiseValue )then:
大家好,提前感谢您的帮助。 下面是我正在尝试做的事情 function1(){ throw some error(); } function2() { // dosomething suc
我有以下未解析的代码。f2 解决了,所以我不会添加该代码,它是 f1 我有问题。 我调用函数,它到达最里面如果,它调用函数“find”,它执行函数 findId,完美返回 Id,然后执行 editId
我是一名优秀的程序员,十分优秀!