循环不等待承诺的解决(包含嵌套的 firebase 调用)
Loop not waiting for resolution of promise (containing nested firebase call)
我正在尝试在循环内部和外部 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 推荐的方法:
提前致谢。
Does anyone know why the loop does not wait for promise containing call to Firebase database?
这样做的原因是您需要在所有提取完成后调用 setState
。但是,您的代码不会对 wait 执行任何操作。您只需继续循环,一旦完成,调用 setState
。你永远不知道你的抓取是否完成。您需要一种方法来 等待 所有的提取。简而言之,由于同步和异步代码混合存在问题。
你可以试试这个。这个想法是将所有 fetchValueByID
(我在开头添加了 return
)调用映射到一个承诺数组中,然后等待其中的 all解决(使用 Promise.all
)before doing 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 promises = [];
// Faking the snapshot
[{
a: 1,
b: 10
}, {
a: 2,
b: 20
}].forEach(function(data) {
var firstThingsFirst = data.a
var someID = data.b
promises.push(fetchValueByID(someID).then(function(someValue) {
return {
"firstThingsFirst": firstThingsFirst,
"someValue": someValue
};
}));
});
// Wait for all promises to resolve
Promise.all(promises).then(function(results) {
console.log(results);
});
function fetchValueByID(someID) {
// Dummy Promise resolution
// Notice the return here
return new Promise(function(resolve, reject) {
setTimeout(function() {
// Dummy manipulation
resolve(someID * 100);
});
}).then(function(snapshot) {
console.log("snapshot (fetchValueByID) = (below)");
console.log(snapshot);
return snapshot;
})
}
我正在尝试在循环内部和外部 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 推荐的方法:
提前致谢。
Does anyone know why the loop does not wait for promise containing call to Firebase database?
这样做的原因是您需要在所有提取完成后调用 setState
。但是,您的代码不会对 wait 执行任何操作。您只需继续循环,一旦完成,调用 setState
。你永远不知道你的抓取是否完成。您需要一种方法来 等待 所有的提取。简而言之,由于同步和异步代码混合存在问题。
你可以试试这个。这个想法是将所有 fetchValueByID
(我在开头添加了 return
)调用映射到一个承诺数组中,然后等待其中的 all解决(使用 Promise.all
)before doing 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 promises = [];
// Faking the snapshot
[{
a: 1,
b: 10
}, {
a: 2,
b: 20
}].forEach(function(data) {
var firstThingsFirst = data.a
var someID = data.b
promises.push(fetchValueByID(someID).then(function(someValue) {
return {
"firstThingsFirst": firstThingsFirst,
"someValue": someValue
};
}));
});
// Wait for all promises to resolve
Promise.all(promises).then(function(results) {
console.log(results);
});
function fetchValueByID(someID) {
// Dummy Promise resolution
// Notice the return here
return new Promise(function(resolve, reject) {
setTimeout(function() {
// Dummy manipulation
resolve(someID * 100);
});
}).then(function(snapshot) {
console.log("snapshot (fetchValueByID) = (below)");
console.log(snapshot);
return snapshot;
})
}