javascript - redux thunk 不等待任何承诺

javascript - redux thunk doesn't wait for any promise

我有一个这样的数组

array =[ {message:'http://about.com'}, {message:'http://facebook.com'}]

我想循环那个数组,在每一项我都会向服务器发出请求以获取 opengraph 数据,然后将数据保存回数组。这就是我所期望的

array =[ 
    {
        message: { url:'http://about.com', title:'about'}
    }, 
    {
       message:{ url:'http://facebook.com', title:'facebook'}
    }
]

然后当一切都结束的时候。我想用有效载荷分派一个动作是预期的数组。这是我的做法

return dispatch => {

    let array =[ {message:'http://about.com'}, {message:'http://facebook.com'}]

    let quests = array
    .map( (item) => {
        axios.get(getOpenGraphOfThisLink + item.message)
        .then( result =>{
            item.message = (result.data)
            return result
        })
    })

    Promise.all(quests).then( () => {
        console.log( 'modified', array)
        dispatch({
            type   : constant.GET_POST_COLLECTION_SUCCESS,
            payload: array
        })
        // this dispatch function sends my original array instead of modified one.
    })
}

问题:代码中的调度函数会将我的原始数组发送到 reducer 而不是修改后的数组。我想分派发送新修改的数组。我认为应该,不是吗?

现在 quests 变量只是由您的原始数组分配,因为 map 函数 return 无效,但您需要 return 每个项目的承诺quests,所以只需添加 return 关键字,这样您的代码就可以像这样:

let quests = array
    .map( (item) => {
        return axios.get(getOpenGraphOfThisLink + item.message)
        .then( result =>{
            item.message = (result.data)
            return result
        })
    })

这是一个范围界定问题。您肯定引用了错误的变量:

return dispatch => {

    let array =[{ // <- the original array
      message:'http://about.com'
    }, {
      message:'http://facebook.com'
    }]

    let quests = array.map( (item) => {
        axios.get(getOpenGraphOfThisLink + item.message)
        .then( result =>{
            item.message = (result.data)
            return result
        })
    })

    Promise.all(quests).then(() => {
        console.log( 'modified', array) // <- here, array is reference to the original array
        dispatch({
            type   : constant.GET_POST_COLLECTION_SUCCESS,
            payload: array
        })
        // this dispatch function to send my original array instead of modified one.
    })
}

您传递给 Promise#then 的函数应该接受一个参数,即 Promise 的解析结果。在 Promise.all 的情况下,这个单个参数是一个结果数组,每个项目都引用具有相应索引的 Promise。所以应该是

return dispatch => {

    let array =[{
      message:'http://about.com'
    }, {
      message:'http://facebook.com'
    }]

    let quests = array.map( (item) => {
        return axios.get(getOpenGraphOfThisLink + item.message) // don't forget to return when doing Array#map.
        .then( result =>{
            item.message = (result.data)
            return result
        })
    })

    Promise.all(quests).then((array) => { // <- the new array, redefined in scope of this arrow function
        console.log( 'modified', array) // <- here, array is reference to the new array which is the first argument of function passed to Promise#then.
        dispatch({
            type   : constant.GET_POST_COLLECTION_SUCCESS,
            payload: array
        })
        // this dispatch function will send the results of calling all the Promises passed to Promise.all!
    })
}

如果我没理解错的话,你是在用 result.data 完成每个请求后改变 array.message

IMO,你不应该这样做

let quests = array.map((item) => {
    return axios.get(getOpenGraphOfThisLink + item.message)
                .then(result => result.data)
})

Promise.all(quests).then((values) => {
  // values contains all the result data.
}

不要忘记处理错误情况。

允许函数改变传递给它的项目通常不是好的做法。

在这种情况下,如果某些 axios.get() 成功而某些失败,您最终会得到一个部分变异的数组,这很可能是不受欢迎的。

相反,您可以映射到原始项目的突变 克隆 的数组,并将映射的数组传递到承诺链中。

假设不涉及"getters",可以使用Object.assign()进行克隆体的克隆和变异

let quests = array.map(item => {
    return axios.get(getOpenGraphOfThisLink + item.message)
    .then(result => Object.assign({}, item, { message: result.data });
});

return Promise.all(quests).then(arr => {
    console.log('mapped', arr); // note 'mapped', not 'mutated'
    // 'x'
    dispatch({
        'type': constant.GET_POST_COLLECTION_SUCCESS,
        'payload': arr
    });
});

现在,如果您真的想改变原始数组,您可以在点 'x' 处以全有或全无的方式进行操作:

Object.assign(array, arr);