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. 中国移动能力开放商店OneNET View数据可视化公测 10分钟轻便生成行业可视化界面

    随着云计算,5G技术,人工智能等底层技术的发展,万物互联时代已经到来,同时带来了海量数据,如何效果好.低成本.短时间的表现据,成为物联网行业从业者和公司的当务之急. OneNET View传统的数据展 ...

  2. 【Linux基础】Linux命令date 日期时间

    1.显示到纳秒 date +%F.%H:%M:%S.%N --:38.740127086 date +%Y-%m-%d.%H:%M:%S.%N2019-04-25.00:28:24.060756673 ...

  3. python从开始到放弃的途中一直很菜的day13

    一直很菜的今天又来了两个新的概念,一个是装饰器,一个是推导式,装饰器好比女生出门前需要化妆的准备,推导式也称为生成式.先说装饰器吧,装饰器其实本质也是一个函数,并用@+函数名装饰到其他函数上,当这个其 ...

  4. STL--关系型容器

    STL--关系型容器 1.树的基本概念 1.1二叉搜索树 二叉搜索树:它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空, ...

  5. 如何把Office365的更新从半年通道改成月度通道

    转自msdn,转发链接:www.cnblogs.com/Charltsing/p/Office365month.html 作者QQ: 564955427 建立一个Bat文件,写入 下面内容 setlo ...

  6. mysql 8.0.X 创建新的数据库、用户并授权

    一.创建数据库 mysql> create database jira; Query OK, 0 rows affected (0.09 sec) 二.创建用户 mysql> create ...

  7. JS confirm或alert对话框中的换行

    如题. alert.confirm对话框的换行可以使用回车符或换行符:\n,\r 也可以使用回车符或换行符对应的unicode编码:\u000a,\u000d,这是等效的. //确认信息 var co ...

  8. 私有仓库 gitlab 部署笔记

    --------------------------------------------gitlab简介------------------------------------------------ ...

  9. 关于Oracle使用管理员账号登录失败的问题

    我在本地建的Oracle数据库在调试自己写的存储过程的时候提示缺少 debug connect session 权限,一般情况下根据这个提示直接用管理员账号登录进去,执行 grant debug co ...

  10. HTML 5 & checkbox & switch components

    HTML 5 & checkbox & switch components <!DOCTYPE html> <html lang="zh-Hans" ...