首页 > 解决方案 > Javascript:使用异步查询的结果附加到数组

问题描述

我有一个异步函数,我想包含三个异步查询的结果(它们是 firebase firestore 查询)。我循环,并尝试将查询结果附加到更广泛范围内的数组中。不幸的是,brands数组的结果总是空的。这是因为我需要await内部查询吗?有没有更好的方法来完全处理这个问题?

async function getBrandsHelper() {
  var brands = [];
  await db
    .collection("global")
    .doc("display-data")
    .get()
    .then(doc => {
      const displayData = doc.data();
      const keys = ["p1", "p2", "p3"];
      for (const i in keys) {
        const k = keys[i];
        const product = displayData[k];
        db.collection("products")
          .doc(product)
          .get()
          .then(doc => {
            var brandData = { id: product };
            const productData = doc.data();
            brandData["image"] = productData["image"];
            brandData["title"] = productData["title"];
            brandData["description"] = productData["description"];
            brandData["url"] = productData["url"];
            brands.push(brandData);
            return;
          })
          .catch(e => {
            console.error(e);
          });
      }
      return;
    })
    .catch(e => {
      console.error(e);
    });
  return brands;
}

标签: javascriptasynchronouspromisegoogle-cloud-firestore

解决方案


您应该重构代码以使用其中一个async/awaitthen/catch回调。这不是强制性的,但会使您的代码更易于理解。将它们视为实现相同结果的替代方案:使异步代码更易于管理。

这就是你将如何做到的async/await(观察不then/catch参与的方式):

async function getBrandsHelper() {
  let brands = [];
  try {
    // You await for the doc1 to be ready
    const doc1 = await db
      .collection("global")
      .doc("display-data")
      .get();

    const displayData = doc1.data();
    const keys = ["p1", "p2", "p3"];
    for (const i in keys) {
      const k = keys[i];
      const product = displayData[k];

      // You await for each tmpDoc before moving on
      const tmpDoc = await db.collection("products")
        .doc(product)
        .get();

      let brandData = {
        id: product
      };
      const productData = tmpDoc.data();
      brandData["image"] = productData["image"];
      brandData["title"] = productData["title"];
      brandData["description"] = productData["description"];
      brandData["url"] = productData["url"];
      brands.push(brandData);
    }

    return brands;
  } catch (error) {
    console.log(error)
    return []
  }
}

使用回调来做这件事then/catch会有点复杂(由于 for 循环内的异步调用)。您必须将所有 Promises 存储在一个数组中,然后使用类似的东西Promise.all来检索所有要使用的文档。

无论如何,您似乎对 Javascript 中的 Promises 和异步代码缺乏更深入的了解。我建议你在这里阅读更多关于 Promises的内容以及关于 Promises 的使用async/await以及它与这里的 Promise 的关系。


推荐阅读