在一个动作创建者中反应 redux 多个请求
React redux multiple requests in one action creator
我想连续发出 2 个请求,有点像瀑布流。我想先请求一个特定的 pokemon,然后根据返回的 obj 的 payload 类型,我想请求更多信息。我认为最好将它分开给几个动作创建者,但感到奇怪的是 fetchPokemon
以另一个获取结束。这是最佳做法吗?
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))
})
}
}
我不认为把这两个分开有什么特别不对的地方。我要问的一个问题是:"Would I ever call fetchPokemonTypeInfo() directly, not from fetchPokemon()?"。如果没有,那么我只是 return 第二个 .ajax 来自第一个 .done() 函数的调用。如果第一个调用总是一个 dep,那么如果它们只是嵌套,似乎更容易推断出发生了什么。此外,如果你确实想让它们分开,你需要将调度函数以及 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 调用。此外,在您的中间件中,您可以通过允许接受多个请求(可能在数组中)并在返回成功 Promise 之前完全解析它们来扩展其功能。
检查此 link 以供参考:
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);
}
Sagas 使用生成器,"make" 您的异步代码是同步的。这样你就不需要处理承诺中的回调等。这是描述应用程序副作用的一种很好而干净的方式。
我想连续发出 2 个请求,有点像瀑布流。我想先请求一个特定的 pokemon,然后根据返回的 obj 的 payload 类型,我想请求更多信息。我认为最好将它分开给几个动作创建者,但感到奇怪的是 fetchPokemon
以另一个获取结束。这是最佳做法吗?
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))
})
}
}
我不认为把这两个分开有什么特别不对的地方。我要问的一个问题是:"Would I ever call fetchPokemonTypeInfo() directly, not from fetchPokemon()?"。如果没有,那么我只是 return 第二个 .ajax 来自第一个 .done() 函数的调用。如果第一个调用总是一个 dep,那么如果它们只是嵌套,似乎更容易推断出发生了什么。此外,如果你确实想让它们分开,你需要将调度函数以及 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 调用。此外,在您的中间件中,您可以通过允许接受多个请求(可能在数组中)并在返回成功 Promise 之前完全解析它们来扩展其功能。
检查此 link 以供参考: 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);
}
Sagas 使用生成器,"make" 您的异步代码是同步的。这样你就不需要处理承诺中的回调等。这是描述应用程序副作用的一种很好而干净的方式。