2017-02-15 164 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