2016-08-25 125 views
1

我想連續發出2個請求,有點像瀑布一樣。我想先請求一個特定的寵物小精靈,然後根據返回的obj的有效載荷的類型,我想要求更多的信息。我認爲最好將這個分離出來給幾個動作創作者,但是覺得很奇怪,fetchPokemon以另一個獲取結束。這是最佳做法嗎?React在一個動作創建者中的多個請求

export const fetchPokemon = function (pokemonName) { 
    return function (dispatch) { 
    dispatch(requestPokemon(pokemonName)) 
    const requestURL = `http://pokeapi.co/api/v2/pokemon/${pokemonName}/` 
    return $.ajax({ 
     url: requestURL, 
    }).done(function (data) { 
     dispatch(receivePokemon(data)) 
     fetchPokeTypeInfo(data.types[0].type.url) 
    }) 
    } 
} 

... 

export const fetchPokemonTypeInfo = function (url) { 
    return function (dispatch) { 
    dispatch(requestPokemonTypeInfo(url)) 
    return $.ajax({ 
     url: url, 
    }).done(function (data) { 
     dispatch(receivePokemonTypeInfo(data)) 
    }) 
    } 
} 

回答

1

我不認爲打破這兩個問題有什麼特別的錯誤。我會問的一個問題是:「我會直接調用fetchPokemonTypeInfo(),而不是從fetchPokemon()?」。如果不是,那麼我只是從第一個.done()函數返回第二個.ajax調用。如果第一個呼叫總是一個dep,那麼如果他們只是嵌套,就會更容易推斷髮生了什麼。另外,如果你想保持它們分開,你需要將調度函數以及url傳遞給第二個函數,否則dispatch在fetchPokemonTypeInfo()中是未定義的。

更新:

,你可以窩在第一個這樣的第二個電話:

export const fetchPokemon = function (pokemonName) { 
    return function (dispatch) { 
     dispatch(requestPokemon(pokemonName)); 
     const requestURL = `http://pokeapi.co/api/v2/pokemon/${pokemonName}/`; 
     return $.ajax({ 
      url: requestURL, 
     }).done(function (data) { 
      dispatch(receivePokemon(data)); 
      dispatch(requestPokemonTypeInfo(data.types[0].type.url)); 

      return $.ajax({ 
       url: data.types[0].type.url, 
      }).done(function (data) { 
       dispatch(receivePokemonTypeInfo(data)); 
      }); 
     }); 
    } 
} 
+0

你能告訴我你將如何築巢嗎?我不確定這是怎麼可能的,因爲不是每次異步調用都必須通過thunk?我怎麼能接下一個thunk內的thunk? – mangocaptain

1

有一種方法,它提供清潔和可預測的解決方案。

如果您使用的是redux,則可以使用中間件來進行API調用。另外,在您的中間件中,您可以通過允許接受多個請求(可能是數組)來擴展其功能,並在返回成功Promise之前完全解決它們。

檢查此鏈接以供參考: https://github.com/reactjs/redux/blob/master/examples/real-world/middleware/api.js

這是一個實用的中間件,但你必須把它擴大到支持多個請求:)祝你好運!

1

使用終極版,傳奇https://github.com/yelouafi/redux-saga

注:下面的代碼只是一個概念,你就需要爲每個您的需求進行調整。

function* fetchPokemon(action) { 
    try { 
     //fetch1 
     const pokemon = yield call(Api.fetchPokemon, action.payload.pokemonId); 
     //this action will execute only after fetch1 is successful 
     yield put({type: "FETCH_POKEMON_SUCCEEDED", payload: pokemon}); 
     //fetch2 
     const pokemonInfo = yield call(Api.fetchPokemonInfo, types[0].type.url) 
     // execute after fetch2 is successful 
     yield put({type: "FETCH_POKEMON_INFO_SUCCEEDED", payload: pokemonInfo}) 
    } catch (e) { 
     yield put({type: "FETCH_FAILED", message: e.message}); 
    } 
} 

// wait for an action and fire a saga 
function* watchFetchPokemonRequest() { 
    yield* take("FETCH_POKEMON_REQUESTED", fetchPokemon); 
} 

Sagas使用Generators,它使您的異步代碼「同步」。這樣你就不需要處理promise中的回調函數等了。這是描述應用程序副作用的一種很好且乾淨的方式。