Javascript 如何在数组循环中强制执行承诺
我正在尝试获取如何实现承诺和承诺的基础知识。所有这些都在给定的数组循环中,例如,来自firebase查询,该查询可以在循环中执行任意数量的操作,然后我可以稍后访问结果。我似乎找不到正确的语法和逻辑。下面是一个示例方法,在该方法中,我想延迟将一些项插入数组,然后在循环完成后访问该数组进行处理 我在StackOverflow上研究了不同的方法。有些人分配一个promises=snap.forEach循环,然后在完成后以某种方式解决这个问题。其他人则在循环中创造承诺。在下面的示例中,我只是使用settimeout来延迟/创建一个异步进程Javascript 如何在数组循环中强制执行承诺,javascript,firebase,promise,Javascript,Firebase,Promise,我正在尝试获取如何实现承诺和承诺的基础知识。所有这些都在给定的数组循环中,例如,来自firebase查询,该查询可以在循环中执行任意数量的操作,然后我可以稍后访问结果。我似乎找不到正确的语法和逻辑。下面是一个示例方法,在该方法中,我想延迟将一些项插入数组,然后在循环完成后访问该数组进行处理 我在StackOverflow上研究了不同的方法。有些人分配一个promises=snap.forEach循环,然后在完成后以某种方式解决这个问题。其他人则在循环中创造承诺。在下面的示例中,我只是使用sett
testfirebaseData = () => {
let channels =[];
var promises=[];
firebase.database().ref('challengeResponses').child(day).once('value', snap => {
snap.forEach(channelChild => {
promises.push(new Promise((resolve) => {
setTimeout(() => {
channels.push(channelChild.key);
resolve(channels)
},1000)
})
)
})
}).then (() => {
Promise.all(promises).then(() => {
console.log(channels[0])
})
}
}
我希望上面的输出显示“channels”数组中的第一个元素,但它总是返回“undefined”。因为我显然没有正确处理承诺。我缺少什么?您的新承诺(…)
应该包装firebase调用,因为这是异步操作。而不是在回调中。回调内部没有异步操作,只有普通数组推送,这是一个同步操作
var promise = new Promise((resolve)=>{
firebase.database().ref('challengeResponses').child(day).once('value', snap => {
var channels=[];
snap.forEach(channelChild => {
channels.push(channelChild.key);
});
resolve(channels);
});
});
promise.then((channels)=>{
console.log(channels);
});
如果您希望整个操作延迟:
var promise = new Promise((resolve)=>{
firebase.database().ref('challengeResponses').child(day).once('value', snap => {
var channels=[];
setTimeout(()=>{
snap.forEach(channelChild => {
channels.push(channelChild.key);
});
resolve(channels);
},1000);
});
});
要模拟嵌套的异步操作,您需要将承诺添加到数组中,就像在外部承诺中解析promissions.all()
,在内部承诺中解析数据一样:
var promise = new Promise((resolve)=>{
firebase.database().ref('challengeResponses').child(day).once('value', snap => {
var snapPromises=[];
snap.forEach(channelChild => {
snapPromises.push(new Promise((snapresolve)=>{
setTimeout(()=>{
snapresolve(channelChild.key);
},1000)
});
});
resolve(Promise.all(snapPromises));
});
});
下面是使用您的代码样式的示例。而不是数组中的对象,我把数字 您不应该在然后中未定义,因为它正在等待承诺执行。如果您试图在然后范围之外显示结果,则只会得到未定义的结果 这段代码没有真正意义,因为您在中显示了一个全局变量,而不是依赖于promise的输出
如果您想将执行延迟1,那么在setTimeout的timeArgument中进行乘法…您能分享一个简单的例子吗?我已尝试设置promises=fiirebase.database()…但也无法实现。我需要在回拨中解决吗?谢谢,但我想使用settimeout来延迟处理,看看会发生什么。如果使用代码,但将数组push放在settimeout内,如settimeout(()=>{channels.push(channelChild.key)},1000)。。。它以“未定义”返回。为什么?因为setTimeout也是一个异步操作,所以在最初的承诺完成之前,它里面的代码不会运行。如果要延迟整个操作,请将forEach()/resolve调用放在setTimeout内。如果您希望forEach的每次迭代都有延迟,那么您需要更改代码,因为forEach不使用或等待promise。settimeout不是放在promise中吗?在这一点上,我们将收集所有的p;Romise并使用Promise.All(promises)执行console.log?我试图使用settimeout来模拟foreach循环中的其他异步逻辑请参阅最新编辑以查看模拟嵌套异步操作谢谢,这就是我要寻找的。firebase调用已经返回了一个promise,所以我只需要在这个逻辑中添加一个.then(),然后调用promise.all()。感谢您的反馈!Stange,我复制/粘贴了你的代码并尝试了它…有时结果是1,有时结果是5?不知道为什么会不一致?更重要的是,我在代码中实现了相同的逻辑(保留我的firebase查询/循环foreach),但它不起作用…始终返回“Undefined”,即使将其放入then()bloc中,我也会更新我的问题以包含我正在尝试的确切代码。如果愿意,请查看fiddle示例,它总是返回第一个元素,但我想你现在已经解决了你的问题。。。
var promises = [];
let channels =[];
[1, 2, 3, 4, 5].forEach((elm, i) => {
promises.push(new Promise((resolve) => {
setTimeout(() => {
channels.push(elm)
resolve(elm);
}, 1000)
}))
});
console.log(channels[0]) // gives undefined
Promise.all(promises).then(() => {
console.log(channels[0]) // gives 1
})