Javascript 循环未等待承诺的解析(包含嵌套的firebase调用)
我试图在循环内部调用Firebase数据库,并在外部调用Firebase数据库。内部Firebase数据库调用使用从外部Firebase调用和循环返回的数据,这就是为什么它在外部Firebase中运行。然后,应将结果设置为状态 问题 在内部Firebase数据库调用中检索的值未设置为状态 理论 由于Firebase数据库调用是异步的,我猜想内部Firebase数据库调用在循环完成并设置状态之前不会完成。 因此,我为内部Firebase数据库调用创建了一个承诺,以便循环在进入下一项之前等待调用完成。 但是,仍没有设置检索到的值 有人知道为什么循环不等待包含对Firebase数据库的调用的承诺吗 我的尝试Javascript 循环未等待承诺的解析(包含嵌套的firebase调用),javascript,reactjs,firebase,firebase-realtime-database,state,Javascript,Reactjs,Firebase,Firebase Realtime Database,State,我试图在循环内部调用Firebase数据库,并在外部调用Firebase数据库。内部Firebase数据库调用使用从外部Firebase调用和循环返回的数据,这就是为什么它在外部Firebase中运行。然后,应将结果设置为状态 问题 在内部Firebase数据库调用中检索的值未设置为状态 理论 由于Firebase数据库调用是异步的,我猜想内部Firebase数据库调用在循环完成并设置状态之前不会完成。 因此,我为内部Firebase数据库调用创建了一个承诺,以便循环在进入下一项之前等待调用完成
userRef.on("value", function(snapshot) {
var snap = [];
// loop through each branch received from firebase
snapshot.forEach(function(data) {
var firstThingsFirst = data.val().firstThingsFirst;
var someID = data.val().someID;
var myPromise = new Promise(function(resolve, reject) {
userRef.child('somechild').child(someID).once('value').then(function(newSnapshot) {
console.log("newSnapshot = (below)");
console.log(newSnapshot.val());
resolve(newSnapshot.val());
}, function(error) {
// Something went wrong.
console.error("error (below)");
console.error(error);
reject("noValueFound")
});
});
var someValue = "";
myPromise.then(function(valueRetrieved) {
console.log(".then of promise is running...");
console.log("valueRetrieved = (below)");
console.log(valueRetrieved);
someValue = this.checkUndefined(valueRetrieved);
}.bind(this));
var array = {"firstThingsFirst": firstThingsFirst, "someValue": someValue};
snap.push(array);
});
this.setState({
snapshots: snap
});
}.bind(this));
替代尝试:
userRef.on("value", function(snapshot) {
var snap = [];
// loop through each branch received from firebase
snapshot.forEach(function(data) {
var firstThingsFirst = data.val().firstThingsFirst;
var someID = data.val().someID;
var someValue = this.fetchValueByID(someID);
var array = {"firstThingsFirst": firstThingsFirst, "someValue": someValue};
snap.push(array);
});
this.setState({
snapshots: snap
});
}.bind(this));
fetchValueByID(someID) {
userProfileRef.child('someChild').child(someID).once('value').then(function(snapshot) {
console.log("snapshot (fetchValueByID) = (below)");
console.log(snapshot.val());
return snapshot.val();
})
}
我还尝试了Firebase推荐的方法:
setState
。但是,您的代码不需要等待。您只需继续循环,循环完成后,调用setState
。你永远不知道你的抓取是否完成。您需要一种等待所有回迁的方法。简而言之,由于同步代码和异步代码的混合,存在一个问题
你可以试试这个。其思想是将所有的fetchValueByID
(我在开始时添加了一个return
)调用映射到一个承诺数组中,然后等待它们全部解析(使用),然后再执行setState
userRef.on("value", function(snapshot) {
// loop through each branch received from firebase
// AND map to array of promises
var promises = [];
snapshot.forEach(function(data) {
var firstThingsFirst = data.val().firstThingsFirst;
var someID = data.val().someID;
promises.push(this.fetchValueByID(someID).then(function(someValue) {
return {
"firstThingsFirst": firstThingsFirst,
"someValue": someValue
};
}));
});
// Wait for all promises to resolve
Promise.all(promises).then(function(results) {
this.setState({
snapshots: results
});
}.bind(this))
}.bind(this));
fetchValueByID(someID) {
// Notice the return here
return userProfileRef.child('someChild').child(someID).once('value').then(function(snapshot) {
console.log("snapshot (fetchValueByID) = (below)");
console.log(snapshot.val());
return snapshot.val();
})
}
我伪造了所有可能的数据,并将我的解决方案转换为下面一个简单易懂的代码片段
var承诺=[];
//伪造快照
[{
答:1,,
b:10
}, {
答:2,,
b:20
}].forEach(函数(数据){
var firstThingsFirst=data.a
var someID=data.b
push(fetchValueByID(someID).then(function(someValue){
返回{
“第一件事第一”:第一件事第一,
“someValue”:someValue
};
}));
});
//等待所有承诺得到解决
承诺。所有(承诺)。然后(功能(结果){
控制台日志(结果);
});
函数fetchValueByID(someID){
//虚假承诺决议
//注意这里的返回
返回新承诺(功能(解决、拒绝){
setTimeout(函数(){
//虚拟操纵
解析(someID*100);
});
}).then(功能(快照){
log(“快照(fetchValueByID)=(下面)”;
控制台日志(快照);
返回快照;
})
}
有人知道为什么循环不等待包含对Firebase数据库的调用的承诺吗
这样做的原因是,您需要在完成所有获取后调用setState
。但是,您的代码不需要等待。您只需继续循环,循环完成后,调用setState
。你永远不知道你的抓取是否完成。您需要一种等待所有回迁的方法。简而言之,由于同步代码和异步代码的混合,存在一个问题
你可以试试这个。其思想是将所有的fetchValueByID
(我在开始时添加了一个return
)调用映射到一个承诺数组中,然后等待它们全部解析(使用),然后再执行setState
userRef.on("value", function(snapshot) {
// loop through each branch received from firebase
// AND map to array of promises
var promises = [];
snapshot.forEach(function(data) {
var firstThingsFirst = data.val().firstThingsFirst;
var someID = data.val().someID;
promises.push(this.fetchValueByID(someID).then(function(someValue) {
return {
"firstThingsFirst": firstThingsFirst,
"someValue": someValue
};
}));
});
// Wait for all promises to resolve
Promise.all(promises).then(function(results) {
this.setState({
snapshots: results
});
}.bind(this))
}.bind(this));
fetchValueByID(someID) {
// Notice the return here
return userProfileRef.child('someChild').child(someID).once('value').then(function(snapshot) {
console.log("snapshot (fetchValueByID) = (below)");
console.log(snapshot.val());
return snapshot.val();
})
}
我伪造了所有可能的数据,并将我的解决方案转换为下面一个简单易懂的代码片段
var承诺=[];
//伪造快照
[{
答:1,,
b:10
}, {
答:2,,
b:20
}].forEach(函数(数据){
var firstThingsFirst=data.a
var someID=data.b
push(fetchValueByID(someID).then(function(someValue){
返回{
“第一件事第一”:第一件事第一,
“someValue”:someValue
};
}));
});
//等待所有承诺得到解决
承诺。所有(承诺)。然后(功能(结果){
控制台日志(结果);
});
函数fetchValueByID(someID){
//虚假承诺决议
//注意这里的返回
返回新承诺(功能(解决、拒绝){
setTimeout(函数(){
//虚拟操纵
解析(someID*100);
});
}).then(功能(快照){
log(“快照(fetchValueByID)=(下面)”;
控制台日志(快照);
返回快照;
})
}
我认为您无法在firebase的快照数据上运行.map
,因此我尝试使用firebase函数.forEach
,它确实循环遍历数据,但我得到了一个错误,即未捕获(承诺中)类型错误:当承诺.all(承诺)时,undefined不是一个函数{console.log(结果);})
行尝试运行。仍在尝试解决此错误,但任何建议都将不胜感激!我错过了快照
不是数组
的事实。在快照
上使用forEach
时,我编辑了代码以创建承诺
数组
。啊,我刚刚尝试过这个同样的修订版!是的,。将承诺推入数组非常有效!我第一次使用Promise.all()
现在感觉很好!非常感谢!听到这个消息很高兴!希望工作示例能帮助您更好地理解它。是的!看到它的运行非常好。感谢您花时间帮助我了解更多:)我认为您无法从firebase对快照数据运行.map
,因此我尝试使用firebase函数。例如每个
,它确实在数据中循环,但我得到一个错误,Uncaught(in promise)TypeError:undefined不是一个函数