【问题标题】:Firebase Cloud Firestore query returning Promise { <pending> } instead of fulfilled when using async/await使用 async/await 时,Firebase Cloud Firestore 查询返回 Promise { <pending> } 而不是已完成
【发布时间】:2020-11-29 01:16:51
【问题描述】:

This question 类似,但没有帮助。

目标是将 async/await 与 Firebase Cloud Firestore 查询一起使用,而不是 the Firebase documentation 中的 then/catch Promise 代码。

但是,下面的函数在否定情况下成功拒绝,但返回 Promise { &lt;pending&gt; } 而不是 Cloud Firestore 文档。

async getUser(emailAddress) {
    // Return null if @emailAddress blank.
    if (!emailAddress) {
        return null;
    }

    // Assume @db points to a Cloud Firestore database. Query only returns one doc.
    let query = db.collection('users').where('emailAddress', '==', emailAddress);
    try {
        let querySnapshot = await query.get();
        querySnapshot.forEach(function(doc) {
           return doc.data();               
        });
    } catch(e) {
        console.log('Error getting user: ', e);
    }
}

【问题讨论】:

    标签: javascript firebase google-cloud-firestore promise es6-promise


    【解决方案1】:

    如果 emailAddress 不为 null 或未定义,则您的函数不返回任何内容,因为forEach() 返回 void。

    由于querySnapshot 中只有一个文档,您可以执行以下操作:

    async getUser(emailAddress) {
        // Return null if @emailAddress blank.
        if (!emailAddress) {
            return null;
        }
    
        // Assume @db points to a Cloud Firestore database. Query only returns one doc.
        const query = db.collection('users').where('emailAddress', '==', emailAddress);
        try {
            const querySnapshot = await query.get();
            return querySnapshot.docs[0].data();               
        } catch(e) {
            console.log('Error getting user: ', e);
        }
    }
    

    请注意,您的 getUser() 函数本身是异步的,因此您需要在它返回的 Promise 实现时使用 then()(或 async/await)来获取 doc 值。

    const emailAddress = "john@gmail.com";
    getUser(emailAddress).
    then(userData => { ... })
    

    【讨论】:

      【解决方案2】:

      您正试图从forEach 返回,但forEach 不返回任何内容,而是循环遍历元素并允许您修改它们。

      您可以像这样修改您的代码,例如:

      async getUser(emailAddress) {
          // Return null if @emailAddress blank.
          if (!emailAddress) {
              return null;
          }
      
          // Assume @db points to a Cloud Firestore database. Query only returns one doc.
          let query = db.collection('users').where('emailAddress', '==', emailAddress);
          try {
              const results = [];
              let querySnapshot = await query.get();
              querySnapshot.forEach(function(doc) {
                 results.push(doc.data());               
              });
              return results;
          } catch(e) {
              console.log('Error getting user: ', e);
          }
      }

      更多关于forEach的信息:

      forEach() 对每个数组元素执行一次回调函数; 不像 map() 或 reduce() 它总是返回值 undefined 并且是 不可链接。典型的用例是在 链的末端。

      【讨论】:

        【解决方案3】:

        async 函数,例如你的函数,总是返回一个承诺。这是无法避免的。所有的异步行为仍然存在于函数中,调用者仍然需要awaitthen 来获取promise 中的值。你不能使用 async/await 来移除一个 Promise 并立即返回。

        最重要的是,您的函数实际上并不返回任何文档。 forEach 中的返回实际上只是从您传递给 forEach 的内联 lambda 函数返回。该返回不会扩展到封闭的 getUser 函数。

        如果您想有效地使用 async/await,该函数仍然必须从其顶层返回一个值。调用者仍然需要使用 await 或 then 来从返回的 promise 中获取值。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-01-27
          • 1970-01-01
          • 1970-01-01
          • 2017-09-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多