如何使数组过滤器与异步函数端一起工作?

时间:2018-11-13 18:30:54

标签: javascript arrays firebase loops asynchronous

我正在开发一个小型纸牌游戏网络应用程序。我正在使用“房间”系统来容纳每个游戏及其玩家。每个房间都有一个玩家列表,我需要过滤此列表以仅获取在Firebase Realtime DB中具有值的玩家列表。在这种情况下,我正在检查他们在/status/{userId}中的用户状态。

我认为我可以很简单地将其组合在一起,但是在过滤器完成之前,已读取了过滤后的players数组或activePlayers

与forEach一起演示:

function debugActivePlayers (players) {
  activePlayers = []
  players.forEach(player => {
   firebase.ref('/status/' + player)
     .once('value')
     .then(snapshot => {
       console.log(snapshot.val()) // 'offline' or 'online' accordingly
       if (snapshot.val() === 'online') activePlayers.push(player)
       return null // <-- IDE throws a fit otherwise lol
     })
  })
  console.log(activePlayers)
}

我希望发生的是:

offline
online
online
[userId1, userId2, userId3]

但是真正发生的是:

[]
offline
online
online

即使内部有异步/承诺逻辑(firebase查询),我如何确保players.forEach(或players.filter)也能同步运行?

1 个答案:

答案 0 :(得分:1)

尝试使用“异步/等待”,如下所示。这将等待所有异步调用完成,然后前进到最后一个console.log

async function debugActivePlayers (players) {
  let activePlayers = []

  for (let player of players) {
    let snapshot = await firebase.ref('/status/' + player).once('value')
    console.log(snapshot.val()) // 'offline' or 'online' accordingly
    if (snapshot.val() === 'online') activePlayers.push(player)
    return null // <-- IDE throws a fit otherwise lol
  }

  console.log(activePlayers)
}

说明-“ for..of”与“ await”使其余语句保持执行状态,直到所有promise都被解决为止。以证明下面的pls测试

function getValue(p) { return Promise.resolve(p) } 

async function test (players = [1,2,3]) {

  for (let player of players) {
    console.log(await getValue(player))
  }

  console.log('done')
}

test()