javascript - 在 firebase 查询中使用 Promise 或 Await

标签 javascript firebase promise async-await

我正在尝试运行一个获取位置集合的查询。然后,它需要根据临时集合检查每个位置,以确保它尚不存在。如果不存在,则进入数组。接下来,它循环遍历数组并随机抓取三个。

这是我的代码:

let locations = []
        let getLocations = db.collection('locations')
            .where('area', '==', 'central')
            .get().then(snapshot => {
                snapshot.forEach(doc => {
                    let loc = doc.data()
                    loc.id = doc.id

                    console.log('1')

                    let locationsplayedRef = db.collection('locationsplayed')
                    locationsplayedRef = locationsplayedRef.where('location_id', '==', loc.id)
                    locationsplayedRef.get().then(snapshot => {
                        // make sure the location is not already in the db
                        if (snapshot.empty) {
                            // only grab activated locations
                            if(!loc.deactivated)
                                locations.push(loc)                    
                        }

                        console.log('2 ', locations)
                    })

                })

            }).then(() => {
                for (let i = locations.length - 1; i > 0; i--) {
                    const j = Math.floor(Math.random() * (i + 1));
                    [locations[i], locations[j]] = [locations[j], locations[i]];
                }

                let third = locations[0];
                let [first, second] = locations.filter(l => !l.restaurant).slice(1);
                let selectedLocations = [first, second, third];

                console.log('3 ', selectedLocations)
            })

当前代码的问题是控制台日志将如下所示 1 3 2 并且我需要 1 2 3。我知道我需要使用 promise 或等待,但我仍然不熟悉使用这些,并且不确定如何使用来实现它。

有人可以告诉我如何使用 Promise 或 Await 以便我的代码按正确的顺序运行吗?

最佳答案

有两个想法会很有用:(1) 因式分解,这样您就可以看到发生了什么,开发更小的、可测试的函数。 (2) Promise.all(),执行循环中生成的每个 Promise。

// return a promise that resolves to the passed loc or null if the loc is played
function isLocationPlayed(loc) {
  let locationsplayedRef = db.collection('locationsplayed')
  locationsplayedRef = locationsplayedRef.where('location_id', '==', loc.id)
  return locationsplayedRef.get().then(snapshot => {
    // make sure the location is not already in the db
    return (snapshot.empty && !loc.deactivated) ? loc : null
  })
}

// return a promise that resolves to an array of locations that have been played
playedLocations() {
  let locations = []
  let getLocations = db.collection('locations').where('area', '==', 'central')
  return getLocations.get().then(snapshot => {
    // build an array of promises to check isLocationPlayed
    let promises = snapshot.docs.map(doc => {
      let loc = doc.data()
      return isLocationPlayed(loc)
    })
    // resolve when all of the passed promises are resolved
    return Promise.all(promises)
  }).then(results => {
    return results.filter(e => e) // remove nulls
  })
}

playedLocations().then(locations => {
  console.log(fyShuffle(locations))
})

// shuffle an array using Fisher Yates
function fyShuffle(a) {
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}

关于javascript - 在 firebase 查询中使用 Promise 或 Await,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60499516/

相关文章:

javascript - AngularJS 的 promise 是缓存

javascript - 使用毕达哥拉斯定理移动地理点

firebase - google_sign_in 包中的 getServerAuthToken 返回 null

swift - 使用 FirebaseUI 删除 Firebase 数据库中的子项

javascript - promise : Resolve returns value too early

javascript - 如何将表值添加为货币?

javascript - 如何将 td 的文本颜色更改为红色

Firebase AB 测试不允许定位 "App Version"

loops - Cypress.io 迭代元素列表以查看文本是否不存在,然后执行操作以添加元素