by Bhuvan Malik

通过布凡·马利克(Bhuvan Malik)

Redux中的功能式React式编程简介 (An introduction to functional Reactive programming in Redux)

Letss start off by getting the basic idea of what “Reactive Programming” is:

首先让我们了解“React式编程”的基本概念:

Reactive Programming is an asynchronous programming paradigm concerned with data streams and the propagation of change.

响应式编程 是一种异步编程范例,涉及数据流和更改的传播。

Reactive Programming is an asynchronous programming paradigm concerned with data streams and the propagation of change.- Wikipedia

响应式编程 是一种异步编程范例,涉及数据流和更改的传播。 -维基百科

ReactiveX or Rx is the most popular API for reactive programming. It’s built on the ideologies of the Observable Pattern, Iterator Pattern, and Functional Programming. Rx has libraries for different languages, but we will be using RxJS.

ReactiveX或Rx是用于React式编程的最流行的API。 它基于可观察模式,迭代器模式和函数式编程的思想。 Rx具有用于不同语言的库,但是我们将使用RxJS 。

Rx基于ObservablesObserversOperators (Rx is based on Observables, Observers, and Operators)

An Observer essentially subscribes to an Observable.

观察者本质上订阅了一个可观察者。

The Observable then emits streams of data which the Observer listens and reacts to, setting in motion a chain of operations on the data stream. The real power comes from Operators or “Reactive Extensions” (hence the term Rx).

然后,Observable发出观察者监听并做出React的数据流,从而在数据流上启动一系列操作。 实际功率来自运营商或“无功分机”(因此称为Rx)

Operators allow you to transform, combine, manipulate, and work with the sequences of items emitted by Observables.

运算符使您可以变换,组合,操纵和使用Observables发出的项目序列。

If you’re not familiar with Rx, you may have a hard time understanding and using Redux-Observable. So I suggest that you get your hands dirty with Rx first!

如果您不熟悉Rx,则可能很难理解和使用Redux-Observable 。 因此,我建议您先使用Rx弄脏手!

Now onto using RxJS with Redux.

现在,将RxJS与Redux结合使用。

可观察到的Redux (Redux-Observable)

Redux-Observable是Redux的基于RxJS的中间件 (Redux-Observable is an RxJS based middleware for Redux)

This is what Redux Docs have to say about middleware in Redux:

这是Redux Docs关于Redux中的中间件的说法:

Middleware provides a third-party extension point between dispatching an action, and the moment it reaches the reducer.

中间件提供了在调度动作与到达减速器之间的第三方扩展点。

Redux middleware can be used for logging, crash reporting, talking to an asynchronous API, routing, and more. Or we can say side effects in general.

Redux中间件可用于记录日志,崩溃报告,与异步API对话,路由等。 或者我们可以说一般的副作用

那么Redux-Observable如何做到所有这些呢? (So how does Redux-Observable do all that?)

Through Epics. Epics are the core primitive of Redux-Observable. An epic is just a simple function that takes in an action and then returns another action. Action In → Action Out. Actions are therefore treated as streams.

通过史诗 。 史诗是Redux-Observable的核心原语。 史诗只是一个简单的函数,它接受一个动作,然后返回另一个动作。 动作输入→动作输出 。 因此,将动作视为流。

Every action dispatched in any component of React will pass through such functions (Epics) as a stream.

在React的任何组件中分派的每个动作都将作为流通过此类功能(Epics)。

Let’s see what a simple Epic that takes in an action 'PING’ and returns a new action 'PONG’ looks like:

让我们看一个简单的Epic,它接受一个action 'PING'并返回一个 action 'PONG'如下所示:

const pingEpic = action$ =>  action$.filter(action => action.type === 'PING')    .mapTo({ type: 'PONG' })

The $ after action is used to indicate that these variables are referencing streams. So we have a stream of actions being passed into the Epic on which we have used the filter operator of RxJS.

$ after action用于指示这些变量正在引用流。 因此,我们将一连串的动作传递到Epic中,在此我们使用了RxJS的filter运算符。

This filter operator filters out all the actions which are not of the type PING! Therefore, the Epic pingEpic is only concerned with handling actions of the type ‘PING’. Finally, this action ‘PING’ is mapped to a new action of the type ‘PONG’ satisfying the main rule of Epics: Action In → Action Out.

该过滤器运算符过滤掉所有非PING type的动作! 因此,Epic pingEpic仅与处理'PING' type 'PING'动作有关。 最后,此action 'PING'被映射到type 'PONG'的新action ,该action符合Epics的主要规则: 动作输入→动作输出

Since every epic is only concerned with a specific type of action, we have a special operator for action$(stream) to filter out unwanted actions from the stream. This operator is the ofType() operator.

由于每个史诗只涉及特定类型的动作,因此我们为action$ (流)有一个特殊的运算符,以从流中过滤掉不需要的动作。 该运算符是ofType()运算符。

Rewriting the previous Epic using ofType we get:

使用ofType重写以前的Epic我们得到:

const pingEpic = action$ =>  action$.ofType('PING')  .mapTo({ type: 'PONG' })

If you want your epic to allow more than one type of action, the ofType() operator can take any number of arguments like so: ofType(type1, type2, type3,...).

如果您希望史诗允许多种类型的动作, ofType()运算符可以采用任意数量的参数,例如: ofType(type1, type2, type3,...)

深入探讨史诗般的运作方式 (Getting Into The Specifics of How Epics Work)

You may think that the action ‘PING’ simply comes in and gets consumed by this epic. That is not the case. There are two things to always remember:

您可能认为动作“ PING”只是进入并被此史诗所消耗。 事实并非如此。 要牢记两件事:

  1. Every action always goes to the reducer first每个动作总是先去减速器
  2. Only after that is that action received by the epic只有在那之后,史诗才能收到那动作

Therefore, the Redux cycle works normally as it should.

因此,Redux循环可以正常工作。

The action ‘PING’ reaches the reducer first and is then received by the Epic, then changed to a new action ‘PONG’ which is dispatched to the reducer.

action 'PING'首先到达减速器,然后由Epic接收,然后更改为新的action 'PONG' ,将其分配给减速器。

We can even access the store’s state inside an Epic because an Epic’s second argument is a light version of the Redux Store! See below:const myEpic = (action$, store) => We can just call store.getState() and access the state inside Epics.

我们甚至可以访问Epic中的商店状态,因为Epic的第二个参数是Redux Store的简明版本! 参见下文: const myEpic = (action$, store) =& > 我们只能ll store.getStat e()并访问Epics内部的状态。

操作员链 (Operator Chaining)

Between receiving an action and dispatching a new one, we can do all sorts of async side effects we want to, such as AJAX calls, web sockets, timers, and so on. This is done using the numerous operators provided by Rx.

在接收到一个动作与调度一个新动作之间,我们可以做各种想要的异步副作用,例如AJAX调用,Web套接字,计时器等。 这是通过Rx提供的众多运算符完成的。

These Rx operators allow you to compose asynchronous sequences together in a declarative manner with all the efficiency benefits of callbacks but without the drawbacks of nesting callback handlers that are typically associated with asynchronous systems.

这些Rx运算符允许您以声明的方式将异步序列组合在一起,同时具有回调的所有效率优势,但没有嵌套通常与异步系统关联的回调处理程序的缺点。

We get the benefits of callbacks, without that notorious ‘callback hell’.

我们获得了回调的好处,而没有臭名昭著的“回调地狱”。

See how we can leverage the power of operators below.

请在下面查看我们如何利用运营商的力量。

常见用例 (A Common Use-Case)

Assume that we want to search for a word with something like a dictionary API using text entered by the user in real-time. We’re basically dealing with storing (in the Redux store) and displaying the results from the API call. We would also like to debounce the API call so that the API is called within, say, 1 second of when the user stops typing.

假设我们要使用用户实时输入的文本,使用字典API之类的词来搜索单词。 基本上,我们正在处理存储(在Redux存储中)并显示API调用的结果。 我们还希望对API调用进行去抖动,以便在用户停止键入后的1秒钟之内调用该API。

This is how it’ll be done using Epic and RxJS operators:

这是使用Epic和RxJS运算符完成的方式:

const search = (action$, store) =>  action$.ofType('SEARCH')  .debounceTime(1000)  .mergeMap(action =>    ajax.getJSON(`https://someapi/words/${action.payload}`)     .map(payload => ({ type: 'SET_RESULTS', payload }))     .catch(payload => Observable.of({type: 'API_ERROR', payload}))  )

Too much to handle?! Don’t worry, let’s break that down.

太多了吗? 别担心,让我们分解一下。

The epic is getting a stream of actions all oftype ‘SEARCH’. Since the user is continuously typing, the payload of every incoming action (action.payload) contains the updated search string.

史诗级的动作全都oftype 'SEARCH' 。 由于用户不断输入内容,因此每个传入操作的有效负载( action.payload )都包含更新的搜索字符串。

The operator debounceTime() is used to filter out some of the actions in the stream except the last one. It basically passes an action through it only if 1 second has elapsed without it receiving another action or observable.

运算符debounceTime()用于过滤掉流中除最后一个动作外的其他动作。 基本上,只有经过1秒而没有收到其他动作或无法观察到时,它才会通过该动作。

We then make the AJAX request, mapping the results to another action 'set_RESULTS' which takes the response data (payload) to the reducer, which is the Action Out part.

然后,我们发出AJAX请求,将结果映射到另一个动作'set_RESULTS' ,该动作将响应数据(payload)传递给减速器,即减速器的“动作”部分。

Any API errors are caught using the catch operator. A new action is emitted with the error details and later displays a toaster with the error message.

使用catch运算符可捕获任何API错误。 发出带有错误详细信息的新操作,稍后显示带有错误消息的烤面包机。

Notice how the catch is inside the mergeMap() and after the AJAX request? This is because the mergeMap() creates a chain that is isolated. Otherwise the error would reach ofType() and will terminate our Epic. If that happens, the Epic will stop listening to any action in the future!

注意在AJAX请求之后,捕获在mergeMap()内部如何? 这是因为mergeMap()创建了一个隔离的链。 否则错误将达到ofType()并终止我们的Epic。 如果发生这种情况,Epic将在将来停止收听任何动作!

We can use traditional promises for AJAX requests as well. However, they have this inherent problem of not being able to get cancelled. So another important use case for using Epics is AJAX cancellation.

我们也可以对AJAX请求使用传统的Promise。 但是,它们具有无法取消的固有问题。 因此,使用Epics的另一个重要用例是AJAX取消。

We use the takeUntil operator to handle this issue. This is done just like we used that catch operator inside mergeMap and after the AJAX request.

我们使用takeUntil运算符来处理此问题。 就像我们在mergeMap和AJAX请求之后使用catch运算符mergeMap

This is because takeUntil must stop the current AJAX request and not the entire Epic! Therefore, isolating operator chains is important here as well.

这是因为takeUntil必须停止当前的AJAX请求,而不是整个Epic! 因此,隔离操作员链在这里也很重要。

Debouncing, throttling, filtering, AJAX cancellation and others, are just the tip of the iceberg. We have a myriad of operators at our disposal, making difficult use-cases trivial to solve. Using these operators, you can get as creative as your imagination allows you to be! Functional Reactive Programming (FRP) is elegant in its own way.

反跳,限制,过滤,AJAX取消等仅是冰山一角。 我们拥有无数的操作员 ,使难以解决的用例变得微不足道。 使用这些运算符,您可以发挥想象力,发挥创造力! 函数式React式编程(FRP)以其自己的方式非常美观。

My focus for this article was on the explanation part of FRP in Redux using Redux-Observable. For setting up Redux-Observable in React+Redux, refer to the official docs — its very well documented, detailed, and easy-breezy.

本文的重点是使用Redux-Observable的Redux中FRP的解释部分。 有关在React + Redux中设置Redux-Observable的信息,请参阅官方文档 -其文档齐全,详细且易于使用。

Be sure to check out my other article on Redux which explores the best practice for creating reducers:

请务必查看我关于Redux的另一篇文章,该文章探讨了创建减速器的最佳实践:

Reducing the Reducer Boilerplate With createReducer()First, a quick recap of what reducers in Redux are:medium.freecodecamp.org

使用createReducer()减少Reducer样板 首先,快速回顾一下Redux中的 Reducer 是什么: medium.freecodecamp.org

Want to improve your JavaScript basics? Give these a read:

是否想改善您JavaScript基础? 阅读以下内容:

JavaScript ES6 Functions: The Good PartsES6 offers some cool new functional features that make programming in JavaScript much more flexible. Let’s talk about…medium.freecodecamp.orgA guide to JavaScript variable hoisting ? with let and constNew JavaScript developers often have a hard time understanding the unique behaviour of variable/function hoisting.medium.freecodecamp.org Function Hoisting & Hoisting Interview QuestionsThis is a part 2 for my previous article on Variable Hoisting titled “A guide to JavaScript variable hoisting ? with…medium.freecodecamp.org

JavaScript ES6功能:优良的部分 ES6提供了一些很酷的新功能,使JavaScript编程更加灵活。 让我们谈谈… medium.freecodecamp.org JavaScript变量提升指南? 使用let和const NewJavaScript开发人员通常很难理解变量/函数hoisting.m edium.freecodecamp.org 的独特行为。 函数提升和提升面试问题 这是我上一篇关于变量提升的文章“ A”的第2部分。 JavaScript变量提升指南? 与…m edium.freecodecamp.org

Peace ✌️

和平✌️

翻译自: https://www.freecodecamp.org/news/an-introduction-to-functional-reactive-programming-in-redux-b0c14d097836/

Redux中的功能式React式编程简介相关推荐

  1. react api_使用Java EE 8中的React式API加速服务

    react api 服务通常可以通过异步处理进行优化,即使不改变其对外界的行为. 某些服务效率不高的原因是,它们需要等待其他服务提供结果才能继续下去. 让我们看一下如何在不等待外部REST服务的情况下 ...

  2. react发送和接收请求_React行为编程简介:请求,等待和阻止

    react发送和接收请求 by Luca Matteis 卢卡·马蒂斯(Luca Matteis) React行为编程简介:请求,等待和阻止 (An intro to Behavioral Progr ...

  3. refract推导_我们如何利用Refract来利用React式编程的力量

    refract推导 by Joe McGrath 通过乔麦克格拉斯 我们如何利用Refract来利用React式编程的力量 (How we harnessed the power of reactiv ...

  4. 笛卡尔函数_笛卡尔,伯克利和函数式React式编程

    笛卡尔函数 by David Valdman 大卫·瓦尔德曼(David Valdman) 笛卡尔,伯克利和函数式React式编程 (Descartes, Berkeley and Functiona ...

  5. 什么是(功能)反应式编程?

    我已经读过关于反应式编程的维基百科文章. 我还阅读了关于功能反应式编程的小文章. 描述非常抽象. 功能反应式编程(FRP)在实践中意味着什么? 反应式编程(与非反应式编程相反?)由什么组成? 我的背景 ...

  6. java中驼峰编码,驼峰式命名法_小驼峰式命名法编程_java中getter和setter

    人们交流靠各种语言,每行都有每行的所谓的"行话".程序员也不例外,众所周知,程序员都是用代码进行交流的.那么除了在代码中的注释之外, 程序员如何读懂别人的程序呢? 当然,程序员之间 ...

  7. 使用Spring Boot和MongoDB构建一个React式应用程序

    "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证. 如果您要 ...

  8. 创建react应用程序_使用SpringWebFlux的React式Web应用程序

    创建react应用程序 1.React式编程简介 React式编程是为具有以下特征的应用程序创造的术语: 非阻塞应用 事件驱动和异步 需要少量线程来垂直扩展(即在JVM中) 就像面向对象的编程,函数式 ...

  9. 流式低代码编程,拖拽节点画流程图并运行

    介绍 今天给大家推荐一款开源项目 flow-eda,后端采用java语言开发,前端有vue3和react两个版本可供选择.主要功能是采用拖拽的形式来完成业务开发,使用对应的功能节点来处理业务,简单.方 ...

最新文章

  1. java找哪一天是星期几_七夕节是几月几日农历时间 2019年七夕情人节哪一天星期几...
  2. python做excel表格教程视频_基于Python实现excel表格读写
  3. *printf()格式化串安全漏洞分析(下)
  4. book1复习 使用java理解程序逻辑
  5. HDU 2277 Change the ball
  6. js 阻止冒泡事件和默认事件
  7. 前排强势围观|云端落地AI,如此超级干货有哪些?
  8. Android Studio 使用笔记:工具窗口浮动与布局恢复
  9. jquery 输入框,单选按钮,下拉列表和复选框的使用
  10. springboot日志框架
  11. Silverlight for Windows Phone 7开发系列(1):环境搭建
  12. C++中result_of用法
  13. react录制mp3格式音频,输出二进制数据流向后台请求音频的url
  14. VGG model 涉及到的paper
  15. Chapter3:字符串编码和文件操作
  16. 提升目标检测模型性能的tricks
  17. Android 蓝牙 Bluetooth 自动回连 取消pin码校验弹出框
  18. MFC-CString
  19. Android关于图片压缩
  20. SQL语句的一个面试题目

热门文章

  1. todolist作业效果
  2. 常量的定义与使用 1006 c#
  3. 数组的遍历 java
  4. django-后台管理-笔记
  5. OpenState之 Mac学习 实验
  6. android 线程那点事
  7. webdynpro 组件重用 传值问题
  8. 商品WEB开发的商品定单与存储过程的应用
  9. 终于知道以后该咋办了!
  10. HTTP3快来了,提前学习一下如何在Nginx中支持HTTP3.0/QUIC