我想将满足某个条件的所有值推送到数组然后返回此数组。这是我的代码
exports.getNearbyPosts = function (myLat, myLng){
var query = firebase.database().ref("posts/").orderByKey();
var listOfItems = [];
query.once("value")
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var key = childSnapshot.key;
var childData = childSnapshot.val();
var dist = getDistanceBetweenCoord(childData.lat, childData.lng, myLat, myLng);
if(dist < 10239820938502){
listOfItems.push(childSnapshot);
}
});
});
return listOfItems;
}
但是因为forEach是异步的,而且好像我不能在forEach上使用回调,所以我返回的listOfItems只是一个空数组。我也试过“.then”,但它只允许我在“.then”中做更多的东西,我想把这个数组作为变量返回到代码的其他部分。在执行forEach后如何返回正确的数组?
答案 0 :(得分:6)
forEach
不是异步(JavaScript, Node.js: is Array.forEach asynchronous?),而是query.once("value")
。您可以通过各种方式解决此问题。使用回调,承诺或等待/异步。
我建议阅读这个非常有用的答案,通过更好的例子来涵盖更多内容:How do I return the response from an asynchronous call?
这里的想法是提供一个函数,可以在完成异步工作后使用结果调用,但是在forEach
中的工作完成之后。
exports.getNearbyPosts = function (myLat, myLng, callback){
var query = firebase.database().ref("posts/").orderByKey();
var listOfItems = [];
query.once("value").then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var key = childSnapshot.key;
var childData = childSnapshot.val();
var dist = getDistanceBetweenCoord(childData.lat, childData.lng, myLat, myLng);
if(dist < 10239820938502){
listOfItems.push(childSnapshot);
}
});
callback(listOfItems)
});
}
getNearbyPosts(0, 0, (result) => {
console.log(result);
});
Promise是处理异步代码的另一种方法。我建议在这里阅读https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises。它会比我更好地解释它们。
以下是使用promises的代码:
exports.getNearbyPosts = function (myLat, myLng){
var query = firebase.database().ref("posts/").orderByKey();
var listOfItems = [];
return new Promise((resolve, reject) => {
query.once("value").then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var key = childSnapshot.key;
var childData = childSnapshot.val();
var dist = getDistanceBetweenCoord(childData.lat, childData.lng, myLat, myLng);
if(dist < 10239820938502){
listOfItems.push(childSnapshot);
}
});
resolve(listOfItems);
});
});
}
getNearbyPosts(0, 0).then(result => {
console.log(result);
});
这实际上可以进一步简化,因为它显示query.once
返回一个承诺本身。我们可以简单地返回query.once
提供给我们的承诺,该承诺将在您的内部函数.then
之后触发一次。我们可以将它们连在一起。
exports.getNearbyPosts = function (myLat, myLng){
var query = firebase.database().ref("posts/").orderByKey();
var listOfItems = [];
// We return the promise created by query.once
return query.once("value").then((snapshot) => {
// our inital .then will do some data filtering
snapshot.forEach((childSnapshot) => {
var key = childSnapshot.key;
var childData = childSnapshot.val();
var dist = getDistanceBetweenCoord(childData.lat, childData.lng, myLat, myLng);
if(dist < 10239820938502){
listOfItems.push(childSnapshot);
}
});
// We return here to continue the chain. The next .then that picks this up will have this result
return listOfItems;
});
}
// Our last promise resolution in the chain, containing listOfItems
getNearbyPosts(0, 0).then(result => {
console.log(result);
});