Javascript 循环未等待承诺的解析(包含嵌套的firebase调用)

Javascript 循环未等待承诺的解析(包含嵌套的firebase调用),javascript,reactjs,firebase,firebase-realtime-database,state,Javascript,Reactjs,Firebase,Firebase Realtime Database,State,我试图在循环内部调用Firebase数据库,并在外部调用Firebase数据库。内部Firebase数据库调用使用从外部Firebase调用和循环返回的数据,这就是为什么它在外部Firebase中运行。然后,应将结果设置为状态 问题 在内部Firebase数据库调用中检索的值未设置为状态 理论 由于Firebase数据库调用是异步的,我猜想内部Firebase数据库调用在循环完成并设置状态之前不会完成。 因此,我为内部Firebase数据库调用创建了一个承诺,以便循环在进入下一项之前等待调用完成

我试图在循环内部调用Firebase数据库,并在外部调用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推荐的方法:

提前谢谢

有人知道为什么循环不等待包含对Firebase数据库的调用的承诺吗

这样做的原因是,您需要在完成所有获取后调用
setState
。但是,您的代码不需要等待。您只需继续循环,循环完成后,调用
setState
。你永远不知道你的抓取是否完成。您需要一种等待所有回迁的方法。简而言之,由于同步代码和异步代码的混合,存在一个问题

你可以试试这个。其思想是将所有的
fetchValueByID
(我在开始时添加了一个
return
)调用映射到一个承诺数组中,然后等待它们全部解析(使用),然后再执行
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承诺=[];
//伪造快照
[{
答:1,,
b:10
}, {
答:2,,
b:20
}].forEach(函数(数据){
var firstThingsFirst=data.a
var someID=data.b
push(fetchValueByID(someID).then(function(someValue){
返回{
“第一件事第一”:第一件事第一,
“someValue”:someValue
};
}));
});
//等待所有承诺得到解决
承诺。所有(承诺)。然后(功能(结果){
控制台日志(结果);
});
函数fetchValueByID(someID){
//虚假承诺决议
//注意这里的返回
返回新承诺(功能(解决、拒绝){
setTimeout(函数(){
//虚拟操纵
解析(someID*100);
});
}).then(功能(快照){
log(“快照(fetchValueByID)=(下面)”;
控制台日志(快照);
返回快照;
})
}
有人知道为什么循环不等待包含对Firebase数据库的调用的承诺吗

这样做的原因是,您需要在完成所有获取后调用
setState
。但是,您的代码不需要等待。您只需继续循环,循环完成后,调用
setState
。你永远不知道你的抓取是否完成。您需要一种等待所有回迁的方法。简而言之,由于同步代码和异步代码的混合,存在一个问题

你可以试试这个。其思想是将所有的
fetchValueByID
(我在开始时添加了一个
return
)调用映射到一个承诺数组中,然后等待它们全部解析(使用),然后再执行
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承诺=[];
//伪造快照
[{
答:1,,
b:10
}, {
答:2,,
b:20
}].forEach(函数(数据){
var firstThingsFirst=data.a
var someID=data.b
push(fetchValueByID(someID).then(function(someValue){
返回{
“第一件事第一”:第一件事第一,
“someValue”:someValue
};
}));
});
//等待所有承诺得到解决
承诺。所有(承诺)。然后(功能(结果){
控制台日志(结果);
});
函数fetchValueByID(someID){
//虚假承诺决议
//注意这里的返回
返回新承诺(功能(解决、拒绝){
setTimeout(函数(){
//虚拟操纵
解析(someID*100);
});
}).then(功能(快照){
log(“快照(fetchValueByID)=(下面)”;
控制台日志(快照);
返回快照;
})

}
我认为您无法在firebase的快照数据上运行
.map
,因此我尝试使用firebase函数
.forEach
,它确实循环遍历数据,但我得到了一个错误,即
未捕获(承诺中)类型错误:当
承诺.all(承诺)时,undefined不是一个函数{console.log(结果);})
行尝试运行。仍在尝试解决此错误,但任何建议都将不胜感激!我错过了
快照
不是
数组
的事实。在
快照
上使用
forEach
时,我编辑了代码以创建
承诺
数组
。啊,我刚刚尝试过这个同样的修订版!是的,
。将承诺推入数组非常有效!我第一次使用
Promise.all()
现在感觉很好!非常感谢!听到这个消息很高兴!希望工作示例能帮助您更好地理解它。是的!看到它的运行非常好。感谢您花时间帮助我了解更多:)我认为您无法从firebase对快照数据运行
.map
,因此我尝试使用firebase函数
。例如每个
,它确实在数据中循环,但我得到一个错误,
Uncaught(in promise)TypeError:undefined不是一个函数