我想连续发出2个请求,有点像瀑布式的方式。我想首先请求一个特定的口袋妖怪,然后基于返回对象的有效载荷类型,我想请求更多信息。我认为最好是将其划分给几个动作创造者,但fetchPokemon
以另一个fetch结尾感觉很奇怪。这是最佳实践吗?
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))
})
}
}
我不认为把这两个人分开有什么特别不对的。我要问的一个问题是:"我会直接调用fetchPokemonTypeInfo(),而不是从fetchPokemon()吗?"如果没有,那么我就返回第一个.done()函数中的第二个.ajax调用。如果第一次调用总是一个深度,那么如果它们只是嵌套,似乎更容易推断出发生了什么。另外,如果你想让它们分开,你需要将分派函数和url传递给第二个函数,否则在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));
});
});
}
}
有一种方法,它提供了清晰和可预测的解决方案。
如果您正在使用redux,您可以使用中间件来进行API调用。此外,在你的中间件中,你可以扩展它的功能,允许接受多个请求(可能在数组中),并在返回成功承诺之前一起解决它们。
查看此链接以供参考:https://github.com/reactjs/redux/blob/master/examples/real-world/middleware/api.js
这是一个功能中间件,但你必须扩展它以支持多个请求:)祝你好运!
使用redux-saga 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);
}
saga使用generator,它"使"你的异步代码同步。这样你就不需要在promises等中处理回调。这是一种描述应用程序副作用的好方法。