最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Firebase Cloud Firestore query returning Promise { <pending> } instead of fulfilled when using asynca

programmeradmin4浏览0评论

This question is similar but didn't help.

The goal is to use async/await with Firebase Cloud Firestore queries instead of the then/catch Promise code from the Firebase documentation.

However, the function below rejects successfully in the negative case, but returns Promise { <pending> } instead of the Cloud Firestore doc.

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);
    }
}

This question is similar but didn't help.

The goal is to use async/await with Firebase Cloud Firestore queries instead of the then/catch Promise code from the Firebase documentation.

However, the function below rejects successfully in the negative case, but returns Promise { <pending> } instead of the Cloud Firestore doc.

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);
    }
}
Share Improve this question asked Aug 9, 2020 at 6:29 CrashalotCrashalot 34.6k63 gold badges284 silver badges460 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

If emailAddress is not null or undefined, your function returns nothing becauseforEach() returns void.

Since you have only one doc in the querySnapshot you can do as follows:

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);
    }
}

Note that your getUser() function is itself asynchronous, so you need to use then() (or async/await) to get the doc value when the Promise it returns is fulfilled.

const emailAddress = "[email protected]";
getUser(emailAddress).
then(userData => { ... })

You are trying to return from forEach, but forEach doesn't return anything, rather it loops through elements and allows you to modify them.

You can modify your code like this for example:

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);
    }
}

More info about 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.

async functions, such as yours, always return a promise. That can't be avoided. All of the asynchronous behavior is still there in the function, and the caller still has to await or then to get the value in the promise. You can't use async/await to remove a promise and return immediately.

On top of that, your function doesn't actually return any documents. The return inside the forEach is actually just returning from the inline lambda function that you passed to forEach. That return doesn't extend to the enclosing getUser function.

If you want to use async/await effectively, the function still has to return a value from its top level. And the caller still has to use await or then to get the value out of the returned promise.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论