Redux thunk中间件

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)。

原文地址:https://www.cnblogs.com/lightsong/p/10428627.html

时间: 2024-10-08 09:15:40

Redux thunk中间件的相关文章

Redux之中间件的原理和applyMiddleware、Thunk的实现

现在我们的Redux和React-Redux已经基本实现了,在Redux中,触发一个action,reducer立即就能算出相应的state,如果我要过一会才让reducer计算state呢怎么办?也就是我们如何实现异步的action呢?这里就要用到中间件(middleware) 1. 中间件(middleware)介绍 中间就是在action与reducer之间又加了一层,没有中间件的Redux的过程是:action -> reducer,而有了中间件的过程就是action -> middl

17. react redux的中间件

1. redux 数据流程图 View 会派发一个 Action Action 通过 Dispatch 方法派发给 Store Store 接收到 Action 连同之前的 State 发给  Reducer 生成新的 State Redux 的 中间件指的是 Action 和 Store 之间 中间件 即指的是 对 Dispatch 方法的封装 或 升级 通过使用 redux-thunk 如果 Action 传递给 Store 的方法是一个函数 它会让函数先执行, 执行完了需要调用Store

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

现在我们的Redux和React-Redux已经基本实现了,在Redux中,触发一个action,reducer立即就能算出相应的state,如果我要过一会才让reducer计算state呢怎么办?也就是我们如何实现异步的action呢?这里就要用到中间件(middleware) 1. 中间件(middleware)介绍 中间就是在action与reducer之间又加了一层,没有中间件的Redux的过程是:action -> reducer,而有了中间件的过程就是action -> middl

react+redux教程(七)自定义redux中间件

教程源代码及目录 https://github.com/lewis617/myReact 今天,我们要讲解的是自定义redux中间件这个知识点.本节内容非常抽象,特别是中间件的定义原理,那多层的函数嵌套和串联,需要极强逻辑思维能力才能完全消化吸收.不过我会多罗嗦几句,所以不用担心. 例子 例子是官方的例子real-world,做的是一个获取github用户.仓库的程序. 本例子源代码: https://github.com/lewis617/myReact/tree/master/redux-e

redux中间件的原理——从懵逼到恍然大悟

前言react已经出来很久了,其生态圈之庞大,一锅炖不下!各种react-xx,已让我们不堪重负,github上随便一个demo,引入的模块至少都是五指之数+.看着头疼,嚼之无味…….在此建议新学者,可以从基础的核心模块学起,前期不要考虑那些数量繁多的马仔小弟,边学边写,个人感觉前期核心要学的流程大致如下:React ——> React + redux + React-redux ——> React + redux + React-redux + React-router ——> Rea

redux中间件和redux-thunk实现原理

redux-thunk这个中间件可以使我们把这样的异步请求或者说复杂的逻辑可以放到action里面去处理,redux-thunk使redux的一个中间件,为什么叫做中间件 我们说中间件,那么肯定是谁和谁的中间,那么redux的中间件指的是谁和谁的中间呢? 如图.view在redux中会派发一个action,action通过store的dispatch方法派发给store,store接收到action,连同之前到state,一起传给reducer,reducer返回一个新到数据给store,sto

redux异步操作学习笔记

摘要: 发觉在学习react的生态链中,react+react-router+webpack+es6+fetch等等这些都基本搞懂的差不多了,可以应用到实战当中,唯独这个redux还不能,学习redux还学的挺久的. 其中困扰我最久的就是redux的异步数据流的处理.难点主要是概念太多,接触的词太多,而且网上的案例看的头都疼,很容易晕,已经晕了好多次了.后来被我简化之后,终于搞懂了,哈哈.!来来来,今天总结一下,希望对大家有所帮助.不过本人主要是介绍redux的异步操作,如果对redux不是很熟

react+redux教程(五)异步、单一state树结构、componentWillReceiveProps

教程目录 react+redux教程(一)connect.applyMiddleware.thunk.webpackHotMiddleware react+redux教程(二)redux的单一状态树完全替代了react的状态机? react+redux教程(三)reduce().filter().map().some().every()....展开属性 react+redux教程(四)undo.devtools.router react+redux教程(五)异步.单一state树结构.compo

react+redux教程(四)undo、devtools、router

上节课,我们介绍了一些es6的新语法:react+redux教程(三)reduce().filter().map().some().every()....展开属性 今天我们通过解读redux-undo的官方示例代码来学习,在redux中使用撤销功能.devtools功能.以及router. 例子 这个例子是个计数器程序,包含计数器.右边的redux开发工具.还有一个路由(不过只有“/”这一个地址). 源代码: https://github.com/lewis617/myReact/tree/ma