Search code examples
javascriptecmascript-6async-awaites6-promisedispatch

Async/Await function is never resolved with Dispatch


In my function below, addToFlatList is only called once, even though I know there are several items in my database to be added. Seems like the fist addToFlatList is never resolved? What am I doing wrong?

photosSnapshot.forEach(async function(childSnapshot) {
    await addToFlatList(childSnapshot.key, childSnapshot.val())(dispatch);
});

addToFlatList function:

const addToFlatList = (photoId, photoObj) => async(dispatch) => { 
    database.ref('users').child(photoObj.author).once('value').then((userSnapshot) => {
        var userInfo = userSnapshot.val();
        dispatch({type: "GOT_USER", payload: userInfo});
    }).catch(error => {
        dispatch({type: "GOT_ERROR"});
    });
}

Update:

Tried to return dispatch like this. addToFlatList is still only called once.

const addToFlatList = async(photoId, photoObj) => {
    return (dispatch) => { 
        database.ref('users').child(photoObj.author).once('value').then((userSnapshot) => {
            var userInfo = userSnapshot.val();
            dispatch({type: "GOT_USER", payload: userInfo});
        }).catch(error => {
            dispatch({type: "GOT_ERROR"});
        });
    }
}

Also tried this:

const addToFlatList = async(photoId, photoObj) => {
    database.ref('users').child(photoObj.author).once('value').then((userSnapshot) => {
        return (dispatch) => { 
          // never hit this point
          var userInfo = userSnapshot.val();
          dispatch({type: "GOT_USER", payload: userInfo});
        }
    }).catch(error => {
        dispatch({type: "GOT_ERROR"});
    });
}

Solution

  • You must return the promise:

    const addToFlatList = (photoId, photoObj) => (dispatch) => { 
        return database.ref('users').child(photoObj.author).once('value').then((userSnapshot) => {
    //  ^^^^^^
            var userInfo = userSnapshot.val();
            return dispatch({type: "GOT_USER", payload: userInfo});
        }).catch(error => {
            return dispatch({type: "GOT_ERROR"});
        });
    };
    

    Alternatively, you must await the promise so that your async function doesn't end prematurely:

    const addToFlatList = (photoId, photoObj) => async (dispatch) => { 
        try {
            const userSnapshot = await database.ref('users').child(photoObj.author).once('value');
    //                           ^^^^^
            var userInfo = userSnapshot.val();
            return dispatch({type: "GOT_USER", payload: userInfo});
        } catch(error) {
            return dispatch({type: "GOT_ERROR"});
        }
    }