浅析`redux-thunk`中间件源码

news/2025/2/12 18:50:01

总觉得文章也应该是有生命力的,欢迎关注我的Github上的博客,这里的文章会依据我本人的见识,逐步更新。

大多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.dispatchlet 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,之后有时间会再总结一下它的用法,如果可以,也愿意再分析下它的源码,欢迎关注。

相关链接

  • 本文在Github上的链接

https://dhexx.cn/news/show-3397123.html

相关文章

CentOS中nginx负载均衡和反向代理的搭建

1: 修改centos命令行启动(减少内存占用): vim /etc/inittab id:5:initdefault: --> 修改5为3 若要界面启动使用 startx 2:安装jdk 1)解压:jdk-7u55-linux-i586.tar.gz[rootlocalhost jdk]# tar -zxvf jdk-7u…

java正则表达式入坑指南

在日常开发工作中,无论你使用的语言是java、python、shell、golang还是C#, 正则表达式是编程语言中几乎绕不开的话题。有了它,可以帮你快速定位到符合条件的文本内容。今天小编带大家一起来学习下正则表达式,相信通过这篇文章的介…

Oracleblockcleanout说明

原 Oracle block cleanout 说明https://blog.csdn.net/tianlesoftware/article/details/6663527版权声明: https://blog.csdn.net/tianlesoftware/article/details/6663527 一. Block Cleanout 说明 文章的整理参考:http://www.orawh.com/60.html 之…

神经网络之卷积和池化(一)

卷积神经网络(CNN)由输入层、卷积层、激活函数、池化层、全连接层组成,即INPUT-CONV-RELU-POOL-FC。 1. 卷积 1.1 单通道、一个卷积核的例子 卷积操作的作用是为了进行特征的提取,下图以 5*5 矩阵 A (一副图像的像素值)&#x…

OpenGL: 反馈

使用glRenderMode设定模式&#xff0c;glFeedbackBuffer进行反馈&#xff0c;glPassThrough使用标记。#include <stdio.h> #include <math.h> #include <Windows.h> #include <gl/GL.h> #include <gl/GLU.h> #include <gl/glut.h> #includ…

Python 自动化运维3-Print输出

Python语言之Print输出方法Print 输出方法&#xff1a; - 表示左对齐 表示正号 0 表示用0填充 f 前指定一个最小宽度 . 指定小数点后的精度 格式:% [flag][width][.precision]typecode 方法1&#xff1a; 1.num 7.9 print the num is %f % num 2.num 7.9 num2 10 print the…

一个能让cin和scanf 一样快的方法:

cin慢是有原因的&#xff0c;其实默认的时候&#xff0c;cin与stdin总是保持同步的&#xff0c;也就是说这两种方法可以混用&#xff0c;而不必担心文件指针混乱&#xff0c;同时cout和stdout也一样&#xff0c;两者混用不会输出顺序错乱。正因为这个兼容性的特性&#xff0c;导…

Oracle 11g 新特性 -- 自适应游标共享(Adaptive Cursor Sharing: ACS) 详解

Oracle 11g 新特性 -- 自适应游标共享(Adaptive Cursor Sharing&#xff1a; ACS) 详解 版权声明&#xff1a; https://blog.csdn.net/tianlesoftware/article/details/7573502 一&#xff0e;自适应游标共享&#xff08;Adaptive Cursor Sharing&#xff09; 说明 1.1 AC…

看来博客要停一阵子

近期忙成狗&#xff0c;看来博客要停一阵子。可能几个月&#xff0c;回来会继续写一些游戏编程精粹的相关学习内容。

android获取其他应用权限(修改状态)

这两天老大发话说要我研究一下安卓安全软件的功能&#xff0c;先抽取了一个小模块&#xff0c;研究权限管理 一开始就去packagemanager 去看发现有几个方法&#xff1a; 就先去看了一下IPackagemanager 里面的方法&#xff1a; 有很多 这里我之列出跟权限有关的 PermissionInf…