Firebase Cloud Firestore 查询在使用 async/await 时返回 Promise { <pending> } 而不是 fulfilled

Firebase Cloud Firestore query returning Promise { <pending> } instead of fulfilled when using async/await

类似但没有帮助。

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

然而,下面的函数在否定的情况下成功拒绝,但 returns Promise { <pending> } 而不是 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);
    }
}

async 函数,例如你的函数,总是 return 一个承诺。这是无法避免的。所有异步行为仍然存在于函数中,调用者仍然必须 awaitthen 才能获得承诺中的值。您不能使用 async/await 删除承诺并立即 return。

最重要的是,您的函数实际上 return 没有任何文档。 forEach 中的 return 实际上只是 return 来自您传递给 forEach 的内联 lambda 函数。 return 没有扩展到封闭的 getUser 函数。

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

您正在尝试从 forEach return,但是 forEach 没有 return 任何东西,而是遍历元素并允许您修改它们。

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

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() executes the callback function once for each array element; unlike map() or reduce() it always returns the value undefined and is not chainable. The typical use case is to execute side effects at the end of a chain.

如果 emailAddress 不为 null 或未定义,则您的函数 returns 没有任何内容,因为 forEach() returns 无效。

由于您在 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() 函数本身是异步的,因此您需要使用 then()(或 async/await)在 Promise it returns 时获取文档值满足了。

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