浅析redux-thunk中间件源码

大多redux的初学者都会使用redux-thunk中间件来处理异步请求,其理解简单使用方便(具体使用可参考官方文档)。我自己其实也一直在用,最近偶然发现其源码只有一个函数,考虑到其在Github上至今有6747个赞,因此比较好奇它究竟给出了一个怎么样的函数。

什么是thunk?

在看具体的源码之前,我们先看一个词thunk,理解这个词有助于我们理解源码。

A thunk is a function that wraps an expression to delay its evaluation. 维基百科中是这样解释thunk的: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的源码非常简洁,出去空格一共只有11行,这11行中如果不算上},则只有8行。最后三行模块的导出方法很好理解,

// thunk的内容如下
({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
} // thunk.withExtraArgument的结果如下
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}

thunk.withExtraArgument允许给返回的函数传入额外的参数,它比较难理解的部分和thunk一样,如下:

({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
}

上述代码使用函数参数的解构加上连用三个箭头函数,显得非常简洁,单同时也带来了理解的困难(这也是箭头函数的缺点之一)。把上述代码在babel REPL中转译为ES5语法后,我们看到以下结果:

"use strict";

function createThunkMiddleware(extraArgument) {
return function (_ref) {
var dispatch = _ref.dispatch,
getState = _ref.getState;
return function (next) {
return function (action) {
if (typeof action === "function") {
return action(dispatch, getState, extraArgument);
}
return next();
};
};
};
}

这下,代码一下子我们能看懂了,不过稍等这里的dispatch,getStatenext还有action又是什么?

我们先看看,在reudx中我们如何使用中间件:

let store = createStore(
reducer,
applyMiddleware(thunk)
);

看来,要解开dispatch,getState,next,action从哪里来,我们还需要再看看applyMiddleware的源码,如下:

export default function applyMiddleware(...middlewares) {
return (createStore) => (...args) => {
const store = createStore(...args)
let dispatch = store.dispatch
let chain = [] const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch) return {
...store,
dispatch
}
}
}

可以看出其中middleware执行时传入的参数对象middlewareAPI中确实包含getStatedispatch两项,next则来自dispatch = compose(...chain)(store.dispatch)这一句中的store.dispatch,而actiondispatch某个action时传入。

一般来说一个有效携带数据的action是如下这样的:

{
type: ADD_TODO,
text: 'Build my first Redux app'
}

加入redux-thunk后,action可以是函数了,依据redux-thunk的源码,我们可以看出如果传入的action是函数,则返回这个函数的调用,如果本身传入的函数是一个异步函数,我们完全可以在函数调用结束后,获取必要的数据再次触发dispatch由此实现异步效果。

小结

redux-thunk的源码总的来说还是很简单的,理解这个函数本身并不难,但是在彻底弄懂每一项却需要对reudx的部分源码有所了解。react官方文档中的Middleware一节讲解的非常好,也确实帮我理解了中间件的工作原理,非常推荐阅读。之前一直使用redux-thunk做异步处理,这段时间尝试了一下redux-saga,它非常优雅,可用于处理更加复杂的异步action,之后有时间会再总结一下它的用法,如果可以,也愿意再分析下它的源码,欢迎关注。

redux-thunk中间件源码的更多相关文章

  1. laravel中间件源码分析

    laravel中间件源码分析 在laravel5.2中,HTTP 中间件为过滤访问你的应用的 HTTP 请求提供了一个方便的机制.在处理逻辑之前,会通过中间件,且只有通过了中间件才会继续执行逻辑代码. ...

  2. Django-session中间件源码简单分析

    Django-session中间件源码简单分析 settings里有关中间件的配置 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddlew ...

  3. 21.django中间件源码阅读

    回顾: 关于里面的源码流程大家可以全看视频,因为代码的跳动性很大,而且会多次调用通过一方法,所以关于中间源码的部分去找个视频看一看,我写的不是很清楚. # 1 cookie session # 2 f ...

  4. Redux thunk中间件

    redux-thunk https://github.com/reduxjs/redux-thunk Why Do I Need This? Thunks are the recommended mi ...

  5. 重新整理 .net core 实践篇——— 权限中间件源码阅读[四十六]

    前言 前面介绍了认证中间件,下面看一下授权中间件. 正文 app.UseAuthorization(); 授权中间件是这个,前面我们提及到认证中间件并不会让整个中间件停止. 认证中间件就两个作用,我们 ...

  6. Python 实现接口类的两种方式+邮件提醒+动态导入模块+反射(参考Django中间件源码)

    实现接口类的两种方式 方式一 from abc import ABCMeta from abc import abstractmethod class BaseMessage(metaclass=AB ...

  7. Python 实现抽象类的两种方式+邮件提醒+动态导入模块+反射(参考Django中间件源码)

    实现抽象类的两种方式 方式一 from abc import ABCMeta from abc import abstractmethod class BaseMessage(metaclass=AB ...

  8. 基于django中settings中间件源码思想,实现功能的插拔式设计

    这里我们用到一个非常重要的模块,importlib,利用它可以实现字符串转python代码,再利用反射进行操作,这样就可以实现插拔式设计. 一.我们先做个初级的,把所有文件放到初级思想文件夹下: 1. ...

  9. redux设计到源码 --- 美团点评技术团队(转)

    https://tech.meituan.com/redux-design-code.html

随机推荐

  1. 初识MVCSharp

    MVCSharp其实是MVP模式 主要内容 ITask IView IController

  2. Spark Streaming里面使用文本分析模型

    功能:接收来自kafka的数据,数据是一篇文章,来判断文章的类型,把判断的结果一并保存到Hbase,并把文章建立索引(没有代码只有一个空壳,可以自己实现,以后有机会了可能会补上) import org ...

  3. 用Python实现的数据结构与算法:队列

    一.概述 队列(Queue)是一种先进先出(FIFO)的线性数据结构,插入操作在队尾(rear)进行,删除操作在队首(front)进行. 二.ADT 队列ADT(抽象数据类型)一般提供以下接口: Qu ...

  4. PAT 1138 Postorder Traversal [比较]

    1138 Postorder Traversal (25 分) Suppose that all the keys in a binary tree are distinct positive int ...

  5. Sparsity稀疏编码(一)

    稀疏编码来源于神经科学,计算机科学和机器学习领域一般一开始就从稀疏编码算法讲起,上来就是找基向量(超完备基),但是我觉得其源头也比较有意思,知道根基的情况下,拓展其应用也比较有底气.哲学.神经科学.计 ...

  6. jdk eclipse SDK下载安装及配置教程

    原文地址https://blog.csdn.net/dr_neo/article/details/49870587 最新鲜最详细的Android SDK下载安装及配置教程 最近Neo突发神经,想要将学 ...

  7. ubuntu-未信任的应用程序启动器-XX-Net.desktop

      在安装启动xxnet时使用sudo命令,该软件打开后提示[未信任的应用程序启动器]如图所示,解决办法简介:(1)更换成root用户(2)更改权限   背景描述 xx-net中的启动程序有权限设置, ...

  8. zw版【转发·台湾nvp系列Delphi例程】HALCON SqrtImage

    zw版[转发·台湾nvp系列Delphi例程]HALCON SqrtImageHALCON SqrtImage 範例 (RAD Studio XE Delphi x64) zw版[转发·台湾nvp系列 ...

  9. EF Code First 学习笔记:约定配置(转)

      要更改EF中的默认配置有两个方法,一个是用Data Annotations(在命名空间System.ComponentModel.DataAnnotations;),直接作用于类的属性上面;还有一 ...

  10. 什么是ASCII码文本文件

    标准ASCII码方式(也称文本方式)存储的文件,更确切地说,英文.数字等字符存储的是ASCII码.文本文件中除了存储文件有效字符信息(包括能用ASCII码字符表示的回车.换行等信息)外,不能存储其他任 ...