开发者问题收集

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

2020-08-09
2387

这个问题 类似,但没有帮助。

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

但是,下面的函数在否定情况下成功拒绝,但返回 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);
    }
}
3个回答

如果 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() 函数本身是异步的,因此您需要使用 then() (或 async/await)在其返回的 Promise 得到满足时获取文档值。

const emailAddress = "[email protected]";
getUser(emailAddress).
then(userData => { ... })
Renaud Tarnec
2020-08-09

您尝试从 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() 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.

Yair Cohen
2020-08-09

async 函数(例如您的函数) 始终 返回一个承诺。这是无法避免的。所有异步行为仍存在于函数中,并且调用者仍必须 awaitthen 才能获取承诺中的值。您不能使用 async/await 删除承诺并立即返回。

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

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

Doug Stevenson
2020-08-09