【问题标题】:javascript - redux thunk doesn't wait for any promisejavascript - redux thunk 不等待任何承诺
【发布时间】: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而不是修改后的数组。我想调度发送新的修改数组。而且我认为应该是,不是吗?

【问题讨论】:

    标签: javascript promise redux redux-thunk


    【解决方案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
            })
        })
    

    【讨论】:

    【解决方案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);
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-31
      • 2019-04-18
      • 1970-01-01
      • 2018-08-27
      • 2018-12-28
      • 2016-11-29
      • 2019-06-30
      相关资源
      最近更新 更多