重要的是,reducer 总是同步的。因此,reducer 不应该收到承诺。操作应仅包含纯数据并采用以下形式:
{
type: 'ADD_TODO',
payload: {
text: 'Do something.'
}
}
redux-promise 允许我们在动作的负载中加入一个承诺。
一旦将 redux-promise 添加到中间件链中,我们就可以调度在其有效负载属性中具有承诺的操作。
redux-promise 中间件将在到达 store 之前处理此操作,并在 promise 被解决或拒绝后调度任何进一步的操作,并且有效负载将包含每种情况下的响应或错误。
一旦 promise 被解决或拒绝,redux-promise 调度的这些进一步的动作是同步的,就像调度的任何动作一样。请记住,我们中间件的工作是在动作负载中的承诺已解决或被拒绝之后调度其他动作。
调度动作 --> 中间件(redux-promise 调度进一步的动作) --> 减速器从这些进一步的动作中获取错误或数据 --> 存储由减速器更新
这是一个独立的示例,我们将向开放的电影数据库 api 请求电影数据,以演示 redux-promise 的工作原理。
先去商店
store.js
import { createStore, combineReducers, applyMiddleware } from 'redux'
import promiseMiddleware from 'redux-promise'
let rootReducer = combineReducers(reducers)
let store = createStore(
rootReducer,
applyMiddleware(promiseMiddleware)
)
现在我们需要将 Redux 的 applyMiddleware 函数作为参数传递给创建 store,然后将 redux-promise 作为参数提供给 applyMiddleware。
现在是动作创建者。
当在下面调用 action creator 函数时,将发出 axios 请求。这个请求会返回一个 promise,然后通过我们的 redux-promise 中间件传递。
actions/index.js
export function requestMovie(movieTitle) {
// create the url for our api request
const url = `http://www.omdbapi.com/??=${movieTitle}&y=&plot=short&r=json`
return { // return our action
type: 'REQUEST_MOVIE',
payload: axios.get(url) // this .get method returns a promise
}
}
然后我们的 reducer 将得到我们承诺的结果。
主函数处理在 promise 被拒绝或解决后由 redux-promise 中间件调度的操作
reducers/index.js
import { combineReducers } from 'redux';
const rootReducer = combineReducers({
movies: movies,
err: err
});
function err(err = false, action){
switch (action.type) {
case 'REQUEST_MOVIE':
return(action.payload.response.status !== 200)
}
return err;
}
function movies(movies = [], action){
switch (action.type) {
case 'REQUEST_MOVIE':
// if promise was not rejected the data property on our action payload will exist comprising the movie data that we requested
if(action.payload.response.status === 200){
return [...movies, action.payload.response.data]
} else{
return [movies]
}
}
return movies
}
export default rootReducer;