Redux 异步数据流-- thunk中间件源码解析

Thunk 引入背景

这是一个关于Redux异步数据流的故事。引入thunk中间件的完整故事在Redux官方中文文档异步数据流。一句话总结就是:原生Redux只支持同步数据流,所以需要引入中间件(middleware) Thnuk 来支持异步数据流。这里有两个关键字:中间件和异步。

Thunk 是什么

A thunk is a function that wraps an expression to delay its evaluation.

// calculation of 1 + 2 is immediate
// x === 3
let x = 1 + 2;

// calculation of 1 + 2 is delayed
// foo can be called later to perform the calculation
// foo is a thunk!
let foo = () => 1 + 2;

用Thunk传递的Action有什么特征

  • An action creator that returns a function to perform asynchronous dispatch.
  • An action creator that returns a function to perform conditional dispatch.
function incrementIfOdd() {
  return (dispatch, getState) => {
    const { counter } = getState();

    if (counter % 2 === 0) {
      return;
    }

    dispatch(increment());
  };
}

Thunk 怎么用

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
const storeWithMiddleware = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

function makeASandwichWithSecretSauce(forPerson) {
  return function (dispatch) {
    return fetchSecretSauce().then(
        ........
    );
  };
}

// Thunk middleware lets me dispatch thunk async actions
// as if they were actions!
storeWithMiddleware.dispatch(
  makeASandwichWithSecretSauce('Me')
);

以上只是一个简单的总结,具体可以参考github上Thunk 官方文档

接下来步入正题:

Redux Thunk 源码

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就是一个嵌套函数。但又感觉啥也没看,还是不知道thunk是干啥的。。。。

我们先假设extraArgument为空,这样可以把问题简单化。

我在看这段源码时想了一下为啥感觉看了像没看一样,总结出了三个待回答的问题:

1. dispatch, getState 哪儿来的?
2. next干啥的?
3.为啥会有这种操作:action(dispatch, getState, extraArgument);

注:action作为一个用户自己根据业务逻辑自己编写的异步函数也不可能用redux中的dispatch和getState作参数呀。

dispatch, getState 哪儿来的?
next干啥的?

我在文章的开头用红色标注过,thunk的本质是中间件(middleware),所以要了解它必须放在Redux applyMiddleware这个大前提下,这样就迎刃而解了。

之前我写过一篇文章:理解Redux底层原理从applyMiddleware开始

首先,thunk是中间件,它的定义符合中间件函数的格式:

// 中间件大致定义格式
middlwware = store => next => action => {
    .....
    let result = next(action)
    .....
    return result;
}

下图是applyMiddleware的部分源码:

applyMiddleware

从图中我认为可以回答前两个问题,我就不多说了。

action(dispatch, getState, extraArgument)

首先,涉及到应用到thunk的action creator的合法写法:

let thunkActionCreator = () => (param1, param2) => {
    ....
    param1({actionType: value});
    .....
}
//注意:此时的dispatch其实已经包裹了引入的middleware的逻辑
//dispatch= fn1Middle(fn2Middle(store.dispatch))

storeWithMiddleware.dispatch(
  thunkActionCreator()
);

从thunk的源码中可以看到,dispatch和getState方法分别赋给了param1 和param2(函数作用域链)。

猜你喜欢

转载自blog.csdn.net/Napoleonxxx/article/details/79325953