2017-02-15 106 views
0

我是新来的反应和redux,我面临一个非常奇怪的问题。我有一个动作如下:ajax在渲染后调用负载

export function getStorySnippetsAction(snippetsLink, channel) { 

return dispatch => { 
    let storiesSnoppet = []; 

    for (var i = 0; i < snippetsLink.length; i++) { 

     $.ajax({ 
      url: snippetsLink[i], 
      dataType: 'json', 
      cache: false, 
      success: function (data) { 
       storiesSnoppet.push(data); 
       console.log("xxxxxxxxxxxxxxxxxxxxx"); 
       console.log(storiesSnoppet); 

      }.bind(this) 
     }); 
    } 


    dispatch({ 
     type: "SET_STORY_SNIPPET", 
     payload: {"channel": channel, "storiesSnippet": storiesSnoppet} 

    }); 

}; 

}

正如你可以看到我有一些Ajax调用在一个循环,然后我用dispach设置状态。现在我的问题是ajax调用是异步的,所以当ajax发送请求时,dispach发生并且不会等待所有ajax调用完成。另外,以下是我所得到的,当我打印出控制台payload.action:

console log

正如你可以看到,当对象是折叠它的大小为0,当我展开我可以看到列表中的一些对象。我对这种奇怪行为的唯一猜测是异步调用在渲染之后完成,并且自从componentdidmount(我称之为getStorySnippetsAction)发生后,再次发生再次发生并且我没有看到任何结果。有人告诉我应该把getStorySnippetsAction放在componentdidupdate里面,但是当我这样做的时候,似乎发生了一个无限循环并且页面从不加载(我可以看到,在控制台中,同样的东西被再次写入并获得,这意味着组件做了更新无限调用)。现在我完全卡住了。如果我在componentdDUpUpdate中调用getStorySnippetsAction,我将陷入无限循环,如果我在componentDidMount中调用它,ajax会花费更长的时间,渲染和渲染将与空数组发生,而不是加载ajax结果。

任何人都可以帮忙吗? (即使是一个想法可能会帮助我解决这个问题。)感谢一百万)

+0

嘿,我建议你看看终极版-的thunk。 https://github.com/gaearon/redux-thunk –

+0

@MartinMihaylov我认为OP已经使用了thunk ..否则他们不会用'dispatch'返回一个函数。 – azium

+0

好的,让我试着理解你的问题。从你的代码中,它看起来最初storesSnippet被设置为一个空的数组,所以没有任何东西会出现在你的屏幕上。这里的原因就像你说的那样,ajax调用是异步的。那么,你想要做的是在完成ajax调用之后调用dispatch,是正确的? –

回答

1

这里的想法是,你将每个请求转换为无极并将其存储在数组中。一旦完成每个请求,我们将用数据解决它。最后,一旦数组中的所有promise都解决了,那么我们就调用dispatch解决这个值。

export function getStorySnippetsAction(snippetsLink, channel) { 
 

 
    return dispatch => { 
 
    let storiesSnoppet = []; 
 

 
    for (var i = 0; i < snippetsLink.length; i++) { 
 
     storiesSnoppet.push(new Promise((resolve, reject) => { 
 
     $.ajax({ 
 
      url: snippetsLink[i], 
 
      dataType: 'json', 
 
      cache: false, 
 
      success: function(data) { 
 
      resolve(data); 
 
      console.log("xxxxxxxxxxxxxxxxxxxxx"); 
 
      console.log(storiesSnoppet); 
 
      }.bind(this) 
 
     }); 
 
     })); 
 
    } 
 

 
    Promise.all(storiesSnoppet).then((values) => { 
 
     dispatch({ 
 
     type: "SET_STORY_SNIPPET", 
 
     payload: { 
 
      "channel": channel, 
 
      "storiesSnippet": values 
 
     } 
 
     }); 
 
    }); 
 
    }; 
 
}

+0

谢谢Cheng的工作。只是为了检查我的方法,你认为使用promise.all是个好主意吗?有没有办法处理这一点,而不使用诺言都利用异步和部分加载? (我赞赏任何建议,因为我想采取正确的步骤) –

+0

你说得对。当您需要等待数千个请求才能完成时,这可能是一个问题:)因此,在您进行加载时,可能的想法是,在请求结束时,您会将新的操作与新添加的代码段一起发送给您片段数组(摘自商店)。派遣将在成功功能之内,并且不再需要承诺。此外,你可以限制请求的数量,因此基本上只请求你真正需要的。这些是一些建议,但我相信有图书馆可以帮助吗?我无法想到我的头顶上。 –

+0

我想我只会限制请求的数量并请求需要什么,然后在需要时提出更多请求。 –

1

为什么不把你的调度从async模块回调后,而不是for循环?

实施例:

import parallel from 'async/parallel' 
export function getStorySnippetsAction(snippetsLink, channel) { 

return dispatch => { 
    let storiesSnoppet = []; 
    const ajaxFunctionArray = snippetsLink.map(i => { 
     return function(callback) { 
     $.ajax({ 
      url: snippetsLink[i], 
      dataType: 'json', 
      cache: false, 
      success: function (data) { 
       storiesSnoppet.push(data); 
       callback(null) 
       console.log("xxxxxxxxxxxxxxxxxxxxx"); 
       console.log(storiesSnoppet); 
      }.bind(this) 
     }); 
     }) 
    //it ill make the posts in parallel and them dispatch just after all have finished 

    async.parallel(ajaxFunctionArray, function (err, result) { 
     dispatch({ 
     type: "SET_STORY_SNIPPET", 
     payload: {"channel": channel, "storiesSnippet": storiesSnoppet} 

    }); 
    } 

}; 
+0

谢谢。我需要安装与npm异步/并行吗? –

+0

是啊..你可以用npm或纱线来安装它 – Robsonsjre