redux-thunk源码解析

概述

redux-thunk是redux官方推荐的异步处理中间件,他使用起来很简单,而且你可能想不到的是,这个库一共也就十来行。

基本用法

redux-thunk的使用非常简单,实际上就是在创建action的方法中不再返回一个单纯的action对象,而是返回一个函数。先来看官方示例。

首先redux-thunk是一个redux的中间件,所以在创建store的时候,我们需要应用这个中间件。

1
2
3
4
5
6
7
8
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';

const store = createStore(
rootReducer,
applyMiddleware(thunk)
);

然后是一个异步操作的基本用法,可以看到incrementAsync方法中返回的是一个接收一个dispatch参数的方法,该方法内部可以有异步操作的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const INCREMENT_COUNTER = 'INCREMENT_COUNTER';

function increment() {
return {
type: INCREMENT_COUNTER
};
}

function incrementAsync() {
return dispatch => {
setTimeout(() => {
// Yay! Can invoke sync or async actions with `dispatch`
dispatch(increment());
}, 1000);
};
}

可以看到redux-thunk的使用非常简单。

源码解析

如果你看一下redux-thunk在GitHub上的源码,你会发现他的实现比使用还简单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}

return next(action);
};
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;

以上就是redux-thunk的全部源码,可以看到,最终传给applyMiddleware的参数是createThunkMiddleware中的返回值,也就是一个redux的中间件。

来回顾一下中间件的格式是怎样的。

1
2
3
4
5
6
const myMiddleware = store => next => action => {
// do something
let result = next(action)
// do something
return result
}

createThunkMiddleware的返回值就是符合这样一个格式的函数,只是其中的dispatch和getState属性从参数store中被解构赋值了出来,实际上中间件中的store是一个简化版的store,只能访问这两个属性。

我们知道,redux中间件是劫持dispatch用的,它能让我们在真正分发action之前或之后做一些自定义的逻辑。

那redux-thunk做了什么呢?其实redux-thunk就是判断了一下action是不是一个函数,如果是一个函数,则执行,否则向下一个中间件传递action。

结合redux-thunk的用法可以得知,action构建函数中如果返回函数,就会被redux-thunk的中间件劫持并执行。

另外还有一个注意点需要注意的是,被redux-thunk劫持后的action不会再被其他中间件执行(这是当然的,因为redux-thunk的action是一个函数,一般中间件处理不了)。

参考

  1. redux-thunk - gaearon - GitHub