Javascript 使用firebase在给定键数组的情况下获取多个单独的值

Javascript 使用firebase在给定键数组的情况下获取多个单独的值,javascript,firebase,firebase-realtime-database,promise,Javascript,Firebase,Firebase Realtime Database,Promise,我正在尝试访问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++) { ke

我正在尝试访问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);
   });
}
问题是,我得到的结果不是全部三个键;我只有一个。我想这是因为
for
循环中的代码是异步的,所以
resolve
只给我第一个键

我如何重写它,以便等待
for
循环完成并返回完整结果。

函数getFirebaseData(key\u arr)
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);
}
{ var ref_obj, 数据_obj={}, 承诺=[]; 对于(变量i=0;i
最小的代码更改可能是这样的。基本上,是为了立即兑现承诺。创建承诺数组并通过
Promise.all
函数getFirebaseData(key\u arr)解析它
{
var ref_obj,
数据_obj={},
承诺=[];
对于(变量i=0;i

最小的代码更改可能是这样的。基本上,是为了立即兑现承诺。创建承诺数组并通过
Promise对其进行解析。所有

前面的答案都是可靠的,除了返回的承诺解析为
数据对象数组

因此,您需要做的是将循环的每个迭代更改为一个承诺,然后使用
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;
        }, {})
    );
}
通过以下方式传送到旧式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;
        }, {});
    });
}
每个承诺现在都解析为一个数组,基本上
[键,值]

.then after Promise.all将所有这些结果组合到一个对象中,如:
{key1:value1,key2:value2,

上面的代码使用了
。once('value')
而不是
。on('value'
)-正如评论中指出的,使用
。on
会让听者附加。因为承诺只能解决一次,所以使用
。once


前面的答案是可靠的,除了返回的承诺解析为一个
数据数组\u 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;
        }, {})
    );
}
通过以下方式传送到旧式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;
        }, {});
    });
}
每个承诺现在都解析为一个数组,基本上
[键,值]

.then after Promise.all将所有这些结果组合到一个对象中,如:
{key1:value1,key2:value2,

上面的代码使用了
。once('value')
而不是
。on('value'
)-正如评论中指出的,使用
。on
会让听者附加。因为承诺只能解决一次,所以使用
。once


Jaromanda精心设计的答案的这一微小变化利用了DataSnapshot的特性(这一切都归功于他的设计):


Jaromanda精心设计的答案的这一微小变化利用了DataSnapshot的特性(这一切都归功于他的设计):


谢谢。我会看看我是否可以调整一些。谢谢。我会看看我是否可以调整一些。谢谢你花时间把这些整合起来。
on()
让监听器保持连接。不应该
一次()
是否在此处使用?无。速记箭头函数以这种方式传输,因为它们就是这样做的。返回是多余的。感谢您花时间将这些内容组合在一起。
on()
使侦听器保持连接。不应该
一次()
是否在此处使用?无。速记箭头函数以这种方式传输,因为它们就是这样做的。返回是多余的