【问题标题】:Async/Await function is never resolved with Dispatch异步/等待函数永远不会用 Dispatch 解决
【发布时间】:2019-09-04 17:10:57
【问题描述】:

在我下面的函数中,addToFlatList 只被调用一次,尽管我知道我的数据库中有几个项目需要添加。似乎拳头addToFlatList 永远无法解决?我做错了什么?

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

addToFlatList 函数:

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

更新

试图像这样返回调度。 addToFlatList 仍然只被调用一次。

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

也试过这个:

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

【问题讨论】:

  • 你的数据库 firebase 是偶然的吗?
  • 您的addToFlatList 被标记为async,但awaitreturn 都不是承诺?
  • “从未解决”是什么意思?它永远不会继续到.forEach 的下一次迭代吗?
  • @Bergi 它在异步函数末尾隐式解析为undefined
  • @IvanRubinson Firebase。而且它永远不会继续到下一次迭代。似乎它只是在等待某些东西,但调度被解雇了

标签: javascript ecmascript-6 async-await es6-promise dispatch


【解决方案1】:

你必须返回承诺:

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

或者,您必须等待承诺,以便您的 async 函数不会过早结束:

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

【讨论】:

  • addToFlatList 在两种方法中仍然只调用一次
  • 请注意,我是这样调用 addToFlatList 的:photosSnapshot.forEach(async function(childSnapshot) { await addToFlatList(childSnapshot.key, childSnapshot.val())(dispatch); }); 查看原始问题
  • 可能有更好的方法,但我最终创建了一个临时数组来保存for each 的结果,因为Firebase 仅适用于for each,然后遍历临时数组。它不节省空间,但它有效。目前找不到更好的选择
  • @JAM No. Falco 的解决方案是const allPromises = []; data.forEach(childSnapshot => { allPromises.push(addToFlatList(childSnapshot.key, childSnapshot.val())(dispatch)); }); await Promise.all(allPromises); 适合您的情况
  • @JAM 是的,它会保留调用的顺序。当他们的异步任务完成并不重要时,我们有 Promise.all 来解决这个问题。当然,电话不会互相等待,但这不是你想要的,对吧?如果您需要按顺序处理它们,那么是的,在处理它们之前无法将它们收集到一个数组中,因为forEach 不支持异步迭代。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-06-16
  • 2019-12-15
  • 1970-01-01
  • 2021-10-13
  • 2018-05-06
  • 2017-07-13
  • 2018-04-04
相关资源
最近更新 更多