Javascript返回功能发生得太晚了

时间:2018-01-14 00:03:21

标签: javascript reactjs function react-native

我的代码应该做什么

我正在使用本机创建一个社交媒体应用,我遇到了代码问题。我正在尝试创建一个功能,它可以抓取所有用户组中的所有帖子。为此,我创建了一个循环。对于用户所在的每个组,循环重复一次。每个循环从一个组中获取帖子。每次调用循环时,都会调用一个新函数,该函数从用户所在的新组中获取帖子,然后将帖子返回到原始函数,这会将它们添加到完整的帖子列表中。

问题

获取帖子的功能不会返回帖子。我认为代码不是在等待帖子返回,而是继续前进。基本上,当我在console.log上获取它们的函数上的帖子时,我得到了正确的帖子,但是当我在console.log上发布整个帖子列表时,我什么都没有回来。

我的问题

如何等待某个函数返回一个值,而不是让代码立即继续运行?

我的代码

        runQ(group){
//this function actually gets the posts from the server (from firebase)
    var items = [];
    firebase.database().ref('posts/'+group).limitToLast(
           Math.floor(24/this.state.passGroups.length)*this.state.numOfPosts
        ).orderByKey().once ('value', (snap) => {
          snap.forEach ( (child) => {       
           items.push({
             //post info
         });
         });
    this.setState({passItems: items})
    console.log(items); //logs correct items.
    }).then(()=>{
       if( this.state.passItems.length != 0 ){return this.state.passItems;}
    })
    }


    //gets the user's groups, then sends out a request to each group for the newest posts.
      getItems(){
      //gets groups...
      //...    
    .then(()=>{
    var allItems = [];
    //allItems will be the big list of all of the posts.
    for (i = 0; i < this.state.passGroups.length; i++) {
       //sending request to runQ function to get posts.
       allItems.push(this.runQ(this.state.passGroups[i].name)) //allItems logs as allItems: ,,,,
    }
    })
    }

2 个答案:

答案 0 :(得分:2)

使用async-await使for循环等待每个响应。

首先,您需要退回Firebase呼叫创建的承诺(您目前不会从runQ()功能返回任何内容)。
改变这一行:

firebase.database().ref('posts/'+group).limitToLast(

成:

return firebase.database().ref('posts/'+group).limitToLast(

然后告诉你回调getItems()调用是异步函数并等待来自runQ()的每个响应:

  getItems(){
    //gets groups...
    //...    
    .then(async () => {
      var allItems = [];
      for (var i = 0; i < this.state.passGroups.length; i++) {
        allItems.push(await this.runQ(this.state.passGroups[i].name)) 
      }
    })
  }

答案 1 :(得分:1)

首先,你必须从runQ返回一个承诺:return firebase.database.....

然后在for循环中你可以这样做:

let allPromises = []
for (i = 0; i < this.state.passGroups.length; i++) {
  allPromises.push(this.runQ(this.state.passGroups[i].name))
}
Promise.all(allPromises).then(itemsArray => {
  allItems = allItems.concat(itemsArray)
})

确保在正确的范围内声明了allItems。