redux-thunk

https://github.com/reduxjs/redux-thunk

Why Do I Need This?

Thunks are the recommended middleware for basic Redux side effects logic, including complex synchronous logic that needs access to the store, and simple async logic like AJAX requests.

Motivation

Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.

相对于同步action, 修改state场景, 对于异步场景, 或者 复杂的同步场景, 就需要thunk中间件。

thunk中间件允许actionCreator返回的dispatch的对象, 不再试普通对象的action(包括type 和 payload参数),

而是一个函数,函数入参为 dispatch 和 getState , 在此函数中处理异步调用 或者 复杂条件的 处理。

异步请求的例子:

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);
};
}

条件dispatch例子:

function incrementIfOdd() {
return (dispatch, getState) => {
const { counter } = getState(); if (counter % 2 === 0) {
return;
} dispatch(increment());
};
}

给store添加thunk中间件

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index'; // Note: this API requires redux@>=3.1.0
const store = createStore(
rootReducer,
applyMiddleware(thunk)
);

dispatch a thunk action:

function fetchSecretSauce() {
return fetch('https://www.google.com/search?q=secret+sauce');
} function makeASandwichWithSecretSauce(forPerson) { // Invert control!
// Return a function that accepts `dispatch` so we can dispatch later.
// Thunk middleware knows how to turn thunk async actions into actions. return function (dispatch) {
return fetchSecretSauce().then(
sauce => dispatch(makeASandwich(forPerson, sauce)),
error => dispatch(apologize('The Sandwich Shop', forPerson, error))
);
};
} // Thunk middleware lets me dispatch thunk async actions
// as if they were actions! store.dispatch(
makeASandwichWithSecretSauce('Me')
);

dispatch返回结果实际上是一个promise,可以使用 then语句观察结果:

// It even takes care to return the thunk’s return value
// from the dispatch, so I can chain Promises as long as I return them. store.dispatch(
makeASandwichWithSecretSauce('My partner')
).then(() => {
console.log('Done!');
});

什么是thunk?

https://github.com/reduxjs/redux-thunk

thunk就是一个函数包裹了一个表达式, 表达式延迟执行。

What’s a 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;

The term originated as a humorous past-tense version of "think".

https://en.wikipedia.org/wiki/Thunk#cite_note-1

  一段程序,不立刻执行, 而是在真正使用的地方, 才计算其值。

相关术语:

call by name

lazy evaluation

表现形式为, 使用匿名函数封装, 等待调用执行任务。

In computer programming, a thunk is a subroutine used to inject an additional calculation into another subroutine. Thunks are primarily used to delay a calculation until its result is needed, or to insert operations at the beginning or end of the other subroutine. It can simply be thought of as a function that takes no arguments, waiting to be called upon to do its work. They have a variety of other applications in compiler code generation and modular programming.

如下面的例子:  hypot(3, 4)语句计算比较耗时,将其封装为匿名函数, 在使用的地方调用匿名函数,就相当于执行hypot(3, 4)。

// 'hypot' is a function that returns another function which is already closed over all required data
const hypot = (x, y) => () => Math.sqrt(x * x + y * y);
// 'thunk' is a function that takes no arguments and performs a potentially expensive operation (computing a square root, in this example) and/or causes some side-effect to occur
const thunk = () => hypot(3, 4); // the thunk can then be passed around...
doSomethingWithThunk(thunk);
// ...or evaluated
thunk(); // === 5

  如下wiki描述, thunk为最早使用在ada语言的执行上, 当其执行时候, 对于函数参数的类型, 其实可以在编译的时候通过一些思考(thought)确定, 这个确定的过程, 被称为thunk。

增加编译时候的一点点小时间, 从而提高解释时候的效率, 减少时间, 这个类型推断的过程, 如果在执行阶段执行, 那么会被多次执行; 如果每次执行都是一样结果, 那么完全没有必要多次执行,

在编译时候确定(thought), 或者在过程的第一次执行后确定(thought),进而被缓存起来,可以被多次使用。

这种过程的形式被固化下来,并被推广到其它应用场景, 并被命名为thunk。

Eric Raymond rejects "a couple of onomatopoeic myths circulating about the origin of this term" and cites the inventors of the thunk recalling that the term "was coined after they realized (in the wee hours after hours of discussion) that the type of an argument in Algol-60 could be figured out in advance with a little compile-time thought [...] In other words, it had 'already been thought of'; thus it was christened a thunk, which is 'the past tense of "think" at two in the morning'. See: Raymond, Eric S. (1996). Raymond, Eric S., ed. The New Hacker's Dictionary. MIT Press. p. 445. ISBN 9780262680929. Retrieved 2015-05-25.

http://www.ruanyifeng.com/blog/2015/05/thunk.html

编译器的"传名调用"实现,往往是将参数放到一个临时函数之中,再将这个临时函数传入函数体。这个临时函数就叫做 Thunk 函数。


function f(m){
return m * 2;
} f(x + 5); // 等同于 var thunk = function () {
return x + 5;
}; function f(thunk){
return thunk() * 2;
}

上面代码中,函数 f 的参数 x + 5 被一个函数替换了。凡是用到原参数的地方,对 Thunk 函数求值即可。

这就是 Thunk 函数的定义,它是"传名调用"的一种实现策略,用来替换某个表达式。

为什么要使用redux-thunk?

如下图,阮老师的文章描述, redux框架,将应用分为  action reducer view三个部分,

对于异步获取数据, 或者添加条件过滤数据场景, 这个过程,在view(react.componet)中实现是不合适, 因为其只负责视图展示,

放在reducer中不行了, 因为框架规定reducer只能作为纯函数使用,

这个重任只能交给 action, 实现 thunk action来做中间层逻辑,此逻辑对数据获取和数据更新到状态负责, 术语 redux store的数据管理和维护的范围。

http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_two_async_operations.html

Action 发出以后,过一段时间再执行 Reducer,这就是异步。

怎么才能 Reducer 在异步操作结束后自动执行呢?这就要用到新的工具:中间件(middleware)。

Redux thunk中间件的更多相关文章

  1. Redux的中间件原理分析

    redux的中间件对于使用过redux的各位都不会感到陌生,通过应用上我们需要的所有要应用在redux流程上的中间件,我们可以加强dispatch的功能.最近也有一些初学者同时和实习生在询问中间件有关 ...

  2. Redux 和 Redux thunk 理解

    1: state 就像 model { todos: [{ text: 'Eat food', completed: true }, { text: 'Exercise', completed: fa ...

  3. Redux的中间件Middleware不难,我信了^_^

    Redux的action和reducer已经足够复杂了,现在还需要理解Redux的中间件.为什么Redux的存在有何意义?为什么Redux的中间件有这么多层的函数返回?Redux的中间件究竟是如何工作 ...

  4. 17. react redux的中间件

    1. redux 数据流程图 View 会派发一个 Action Action 通过 Dispatch 方法派发给 Store Store 接收到 Action 连同之前的 State 发给  Red ...

  5. redux进阶 --- 中间件和异步操作

    你为什么需要异步操作? https://stackoverflow.com/questions/34570758/why-do-we-need-middleware-for-async-flow-in ...

  6. 理解 Redux 的中间件

    将该思想抽象出来,其实和 Redux 就无关了.问题变成,怎样实现在截获函数的执行,以在其执行前后添加自己的逻辑. 为了演示,我们准备如下的示例代码来模拟 Redux dispatch action ...

  7. React:快速上手(7)——使用中间件实现异步操作

    React:快速上手(7)——使用中间件实现异步操作 本文参考链接:Stack Overflow redux-thunk 我们使用store.dispath进行派发时,只能传递一个普通对象进去,如下: ...

  8. Redux异步解决方案之Redux-Thunk原理及源码解析

    前段时间,我们写了一篇Redux源码分析的文章,也分析了跟React连接的库React-Redux的源码实现.但是在Redux的生态中还有一个很重要的部分没有涉及到,那就是Redux的异步解决方案.本 ...

  9. Redux和React-Redux的实现(三):中间件的原理和applyMiddleware、Thunk的实现

    现在我们的Redux和React-Redux已经基本实现了,在Redux中,触发一个action,reducer立即就能算出相应的state,如果我要过一会才让reducer计算state呢怎么办?也 ...

随机推荐

  1. 【Spring Cloud笔记】 断路器-hystrix

    在微服务架构中,一个微服务的超时失败可能导致瀑布式连锁反映,Spring Cloud Netflix 的断路器Hystrix通过自主反馈,防止了这种情况发生.下面介绍简单的断路器使用方法. [step ...

  2. Linux学习历程——Centos 7 ls命令

    一.命令介绍 ls命令用于显示目录中的信息. ----------------------------------------------------------------------------- ...

  3. linux使用Nginx搭建静态资源服务器

    最近公司需要做一个宣传片播放  视频有点大 好几百M 就想到使用Nginx来代理静态资源,在过程中出现了一些问题,比如端口没开.访问是403等,没有成功,后面慢慢查找问题,才发现大部分博客资料的都不全 ...

  4. webapi返回json字符串

    第一种 直接在方法中返回json. public class DefaultController : ApiController { [HttpGet] public IHttpActionResul ...

  5. py文件2种执行方式

    import m1# print('模块导入执行', m1.num) # import sys# print(sys.path)import json# print(json) if __name__ ...

  6. Django 使用mysql 创建项目

    一.安装 mysql 和 mysqlclient 1. 安装 mysql ,https://www.jianshu.com/p/07a9826898c0 2. pip3 install mysqlcl ...

  7. SIM 800C指令笔记

    拨号ATD137xxxxxxxx; 挂断-对方挂断收到NO CARRIER消息 挂断-主动挂断ATH 接电话ATA 打入电话消息RING 设置来电电话号码显示AT+CLIP=1显示消息格式:+CLIP ...

  8. 面试7家,收到5个offer,我的Python就业经验总结 !

    *---------------------------------------人生处处有惊喜,背后却是无尽的辛酸苦辣.   Python找工作并不容易,老表面试了很多企业,总结了些宝贵经验! 一周转 ...

  9. springmvc上传文件错误The current request is not a multipart request

    <1>在jsp页面的<head></head>标签里面加上<meta http-equiv="Content-Type" content= ...

  10. css实现垂直水平居中的方法

    html结构: <div class="box"> <div>垂直居中</div> </div> 方法1:display:flex ...