我正在尝试访问Firebase中的多个单独密钥。我正在使用基于承诺的函数和for
循环来迭代给定的键。
以下是代码:
function getFirebaseData(key_arr)
{
var ref_obj,
data_obj = {};
return new Promise(function(resolve)
{
for(var i = 0; i < key_arr.length; i++)
{
key_str = key_arr[i];
ref_obj = firebase.database().ref('path/'+key_str);
ref_obj.on('value', function(snapshot)
{
data_obj[key_str] = snapshot.val();
});
}
resolve(data_obj);
});
}
然后我运行如下:
var key_arr = ['first_key', 'second_key', 'third_key'];
getFirebaseData(key_arr).then(function(result){console.log(result);});
问题是我得到的结果不是全部三个键;我只得到一个。我想这是因为for
循环中的代码是异步的,所以resolve
只给我第一个密钥。
如何以一种等待for
循环完成并返回完整结果的方式重写此内容。
答案 0 :(得分:2)
之前的答案是可靠的,除了返回的promise已解析为data_obj
因此,您需要做的是将循环的每次迭代更改为承诺,然后等待使用Promise.all
解析所有承诺
以下是使用ES2015的方法 - 当你使用Promise时,ES2015无论如何都不是
function getFirebaseData(key_arr) {
return Promise.all(key_arr.map(key_str =>
new Promise((resolve, reject) =>
firebase.database().ref('path/'+key_str).once('value', snapshot =>
resolve ([key_str, snapshot.val()])
)
)
)).then(results =>
results.reduce((result, [key, value]) => {
result[key] = value;
return result;
}, {})
);
}
它转发到旧学校ES5:
function getFirebaseData(key_arr) {
return Promise.all(key_arr.map(function (key_str) {
return new Promise(function (resolve, reject) {
return firebase.database().ref('path/' + key_str).once('value', function (snapshot) {
return resolve([key_str, snapshot.val()]);
});
});
})).then(function (results) {
return results.reduce(function (result, item) {
var key = item[0],
value = item[1];
result[key] = value;
return result;
}, {});
});
}
每个单独的承诺现在解析为一个数组,基本上是[key, value]
在Promise.all之后的.then将所有这些结果合并到一个对象,例如:{ key1: value1, key2: value2,
......
上面的代码使用
是有意义的.once('value'
而不是.on('value'
- 正如评论中指出的那样,使用.on
会使听众附加。由于Promise只能在ONCE中解决,因此使用.once
答案 1 :(得分:1)
function getFirebaseData(key_arr)
{
var ref_obj,
data_obj = {},
promises = [];
for(var i = 0; i < key_arr.length; i++)
{
key_str = key_arr[i];
promises.push(
new Promise(function(resolve)
{
ref_obj = firebase.database().ref('path/'+key_str);
ref_obj.on('value', function(snapshot)
{
data_obj[key_str] = snapshot.val();
});
resolve(data_obj);
})
)
}
return Promise.all(promises);
}
最小的代码更改可以是这个。基本上,而不是立即回报承诺。创建promises数组并通过Promise.all
解析它。
答案 2 :(得分:0)
Jaromanda精心设计的答案的这个微小变化使用了DataSnapshot的key属性(所有这些都归功于他的设计):
function getFirebaseData(key_arr) {
return Promise.all(key_arr.map(key_str =>
firebase.database().ref('path/'+key_str).once('value'))
).then(snapshots =>
snapshots.reduce((result, snap) => {
result[snap.key] = snap.val();
return result;
}, [])
);
}