javascript - redux thunk 不等待任何承诺

Posted

技术标签:

【中文标题】javascript - redux thunk 不等待任何承诺【英文标题】:javascript - redux thunk doesn't wait for any promise 【发布时间】:2017-04-03 00:24:48 【问题描述】:

我有一个这样的数组

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而不是修改后的数组。我想调度发送新的修改数组。而且我认为应该是,不是吗?

【问题讨论】:

【参考方案1】:

现在quests变量只是由你原来的数组赋值,因为map函数返回void,但是你需要将每个项目的promise返回给quests,所以只需添加return关键字,让你的代码是这样的:

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

【讨论】:

直截了当,但请注意我的回答中的附带条件。 我有类似的情况,知道如何解决***.com/questions/40791724/…【参考方案2】:

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

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!
    )

【讨论】:

返回 axios 工作,但是在 then 函数中添加数组参数将不起作用。所以现在我的代码只需添加'return'关键字就可以了。【参考方案3】:

如果我理解正确的话,在使用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.

不要忘记处理错误情况。

【讨论】:

【参考方案4】:

允许函数改变传递给它的项目通常不是一个好习惯。

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

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

假设不涉及“getter”,您可以使用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);

【讨论】:

关于这个案例的任何想法***.com/questions/40791724/…

以上是关于javascript - redux thunk 不等待任何承诺的主要内容,如果未能解决你的问题,请参考以下文章

javascript 使用Redux-Thunk缓存API响应

javascript 动作创作者。他们将使用thunk进行redux调度

javascript Async Await Action Creator with Redux Thunk

javascript - redux thunk 不等待任何承诺

如何使用 redux-thunk `bindActionCreators`

redux-thunk 的唯一好处是啥?