使用firebase获取多个个别值给定一组键
我试图访问Firebase中的多个单独的键。我正在使用基于承诺的函数和for
循环遍历给定的键。使用firebase获取多个个别值给定一组键
下面的代码:
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
循环完成并返回完整的结果。
以前的答案是实心的,除了承诺返回解析为data_obj
所以一个数组,你需要做的是循环的每次迭代改变为一个承诺,然后等待所有的承诺,以解决使用Promise.all
这里是你将如何使用ES2015做到这一点 - 因为你使用的承诺,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;
}, {})
);
}
这transpiles老同学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后。然后所有这些结果组合到一个单一的对象,如:{ key1: value1, key2: value2,
...
上面的代码使用
.once('value'
而不是.on('value'
- 正如在评论中指出的那样,使用.on
会使听者连接。作为承诺只能用一次解决,那么它是有道理的使用.once
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);
}
最小的代码更改可以是这样的。基本上,而是为了即时的回报承诺。创建承诺数组并通过Promise.all
来解决它。
感谢您的支持。将看看我是否可以调整这一些。 –
上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;
}, [])
);
}
感谢您花时间把这些放在一起 –
on()离开了听者的连接。这里不应该用'()'吗? –
好点@BobSnyder –