为什么 nested async/await 没有按预期工作?

why nested async/await doesn't work as intended?

我正在学习 NodeJs,但在使用 async/await 时遇到了一些问题。我正在使用 Firebase 数据库来处理 read/write 数据。这是我在做什么。 (功能齐全,以备不时之需)。

async getImport(reqData: any): Promise<any> {
    const username = 'kdat0310';
    const db = admin.database();
    const userRef = db.ref('/user');
    const importRef = db.ref('/import');
    const refAuthentication = db.ref('/Authentication');
    const keyList = [];
    const providerKey = [];
    const khoList = [];
    let index = 0;
    const providerList = [];
    const isValid = await refAuthentication.once('value', function (snapshot) {
      for (const val of Object.values(snapshot.val())) {
        if (
          Object(val).username === Object(reqData).username &&
          Object(val).token === Object(reqData).token
        ) {
          return true;
        }
      }
      return false;
    });
    if (isValid) {
      await userRef.once('value', function (snapshot) {
        for (const value of Object.values(snapshot.val())) {
          if (value) {
            if (Object(value).username == username) {
              for (const val of Object(value).workAt) {
                if (val) khoList.push(val.khoId);
              }
            }
          }
        }
      });
      const typeAndColorKey = [];
      const typeAndColorValue = [];
      const typeAndColorRef = db.ref('/TypeAndColor');
      await typeAndColorRef.once('value', function (snapshot) {
        let count = 0;
        for (const key in snapshot.val()) {
          typeAndColorKey.push(key);
        }
        for (const value of snapshot.val()) {
          if (value !== undefined && value != null) {
            typeAndColorValue.push({
              id: typeAndColorKey[count],
              type: value.type,
              color: value.color,
            });
            count = count + 1;
          }
        }
      });
      const findTypeAndColor = (id: any) => {
        for (const value of typeAndColorValue) {
          if (id == value.id) {
            return { type: value.type, color: value.color };
          }
        }
      };
      const userKey = [];
      const userList = [];
      await userRef.once('value', function (snapshot) {
        let count = 0;
        for (const key in snapshot.val()) {
          userKey.push(key);
        }
        for (const value of Object(snapshot.val())) {
          if (value != undefined && value != null) {
            userList.push({
              id: userKey[count],
              name: Object(value).name,
            });
            count++;
          }
        }
      });
      const findUserName = (userId: any) => {
        const returnValue = '';
        for (const value of userList) {
          if (userId == Object(value).id) {
            return Object(value).name;
          }
        }
      };
      const importList = [];
      await importRef.once('value', async function (snapshot) {
        const importKey = [];
        const cloneArr = snapshot.val().map((item: any) => {
          return item;
        });
        for (const key in snapshot.val()) {
          importKey.push(key);
        }
        let countTemp = 0;
        for (const value of Object.values(cloneArr)) {
          const goodsKeyList = [];
          let count = 0;

          if (khoList.indexOf(Object(value).warehouseId) !== -1) {
            const listGoodsList = [];
            if (Object(value).listGoods) {
              for (const key in Object(value).listGoods) {
                goodsKeyList.push(key);
              }
              const refListGoods = db.ref(
                '/import/' + importKey[countTemp] + '/listGoods',
              );

              await refListGoods.once('value', function (snapshot) {
                let item: any;
                for (item of Object.values(snapshot.val())) {
                  if (item) {
                    const tempItem = item.filter((n: any) => n);
                    listGoodsList.push({
                      typeAndColor: findTypeAndColor(goodsKeyList[count]),
                      listGoods: tempItem,
                      number: tempItem.length,
                    });
                  }
                  count++;
                }
              });
            }
            console.log('test 1', listGoodsList);
            if (listGoodsList !== []) {
              importList.push({
                listGoods: listGoodsList,
                driver: Object(value).driver,
                userId: Object(value).importEmployee,
                name: findUserName(Object(value).importEmployee),
                orderId: Object(value).orderId,
                warehouseId: Object(value).warehouseId,
                time: Object(value).time,
              });
            }
          }
          countTemp++;
        }
        console.log('test 2', importList);
      });

      return importList;
    }
    return 'Invalid';
  }

问题出现在 await importRef.once 当我尝试处理一些数据并添加 Firebase一旦函数“异步”并在内部等待以将我需要的数据推送到数组。然后 return importList; return 什么都没有。我认为 await refListGoods.once 导致了这个问题。正如我所想,里面的 await 已经完成了它的职责,我可以很好地 console.log importList 里面。但我认为 await importRef.once 也会在 return 之前完成。当我删除 await refListGoods.once 时,return 很好,但我没有得到我需要的数据。我是否需要像上面 findTypeAndColor 和 findUserName 那样重构所有代码,或者有更好的方法来解决这个问题?

如果要在 once 返回的 Promise 上使用 await,则不应向其传递回调函数。

所以代替:

const isValid = await refAuthentication.once('value', function (snapshot) {
  for (const val of Object.values(snapshot.val())) {
    if (
      Object(val).username === Object(reqData).username &&
      Object(val).token === Object(reqData).token
    ) {
      return true;
    }
  }
  return false;
});

做:

const snapshot = await refAuthentication.once('value');
let isValid = false;
snapshot.forEach((child) => {
  const val = child.val();
  if (val.username === Object(reqData).username &&
      val.token === Object(reqData).token
  ) {
    isValid = true;
  }
})