精华内容
下载资源
问答
  • 响应式编程

    2019-05-03 11:45:11
    响应式编程 本文是对Reactor官方文档Introduction to Reactive Programming部分内容的翻译,希望对理解响应式编程的概念和原理有所帮助。 响应式编程是一种异步编程范式,它关注数据流和变化的传播。这意味着可以...

    响应式编程

    本文是对Reactor官方文档Introduction to Reactive Programming部分内容的翻译,希望对理解响应式编程的概念和原理有所帮助。

    响应式编程是一种异步编程范式,它关注数据流和变化的传播。这意味着可以通过使用编程语言轻松地表示静态(例如数组)和动态(例如事件发射器)数据流。

    Reactive Streams为基于JVM的响应库提供了规范,它定义了一组接口和交互规则。在Java 9中,这些接口已经集成到java.util.concurrent.Flow类之下。

    在面向对象编程语言中,响应式编程通常以观察者模式的扩展呈现。还可以将响应式流模式和迭代器模式比较,一个主要的区别是,迭代器基于”拉“,而响应式流基于”推“。

    使用迭代器是一种命令式编程,由开发者决定何时去访问序列中的next()元素。而在响应式流中,与Iterable-Iterator对应的是Publisher-Subscriber。当新的可用元素出现时,发布者通知订阅者,这种”推“正是响应的关键。此外,应用于推入元素上的操作是声明式的而不是命令式的:程序员要做的是表达计算的逻辑,而不是描述精准的控制流程。

    除了推送元素,响应式编程还定义了良好的错误处理和完成通知方式。发布者可以通过调用next()方法推送新的元素给订阅者,也可以通过调用onError()方法发送一个错误信号或者调用onComplete()发送一个完成信号。错误信号和完成信号都会终止序列。

    响应式编程非常灵活,它支持没有值、一个值或n个值的用例(包括无限序列,例如时钟的连续滴答声)。

    但是让我们首先考虑,为什么我们需要响应式编程?

    阻塞可能是浪费的

    现代的应用需要满足大量的用户并发访问,尽管硬件的能力依然在不断提高,软件的性能仍然是一个关键问题。

    通常有两种方法可以提升程序的性能:

    • 并行化:使用更多的线程和更多的硬件资源。
    • 在如何使用现有资源方面寻求更高的效率。

    通常,Java开发者使用阻塞代码编程。在出现性能瓶颈之前,这种做法没有问题,此时就需要引入额外的线程,来运行相似的阻塞代码。但是,这种资源利用率的扩展可能很快引来争用和并发问题。

    更糟糕的是,阻塞会浪费资源。如果仔细观察,只要程序涉及一些延迟(特别是IO,比如数据库请求或网络调用),资源就会被浪费,因为一个(或多个线程)正处于空闲状态,等待数据。

    所以,并行化方法并不是什么灵丹妙药。为了提高硬件资源的利用率,响应式编程是必要的。但是它也很复杂,因为容易造成资源浪费。

    使用异步来解决?

    上文提到的第二种方法是寻求更高的效率,可以解决资源浪费问题。通过编写异步非阻塞代码,你可以将执行切换到另一个使用相同底层资源的活动任务上,在异步执行完成后返回到当前程序。

    如何在JVM上编写异步代码呢?Java提供了两种异步编程模型:

    • Callbacks:异步方法没有返回值,但是提供一个额外的回调参数(一个lambda或者匿名类对象),当结果可用时调用该参数。
    • Futures:异步方法立即返回一个Future<T>对象。异步线程计算一个T值,Future对象封装对它的访问。该值不是立即可用的,但可以轮询Future对象,直到该值可用为止。

    这些技术足够好吗?并不是每个场景都适用,而且两种方式都有限制。

    回调是很难组合在一起的,很快就会导致难以阅读和维护的代码(称为”回调地狱”)。

    Futures比回调稍微好一点,但是在组合方面依然做的不够好,即使Java 8中引入了CompletableFuture。把多个Future编排到一起虽然可行,但是并不容易。而且,Future还有另外的问题:通过调用get()方法,很容易让Future对象进入到另一种阻塞情景;它们不支持延时计算;不支持多值和高级错误处理。

    从命令式编程到响应式编程

    响应式编程库Reactor旨在解决JVM上这些”经典“的异步编程方式的缺点,同时关注几个额外的方面:

    • 可组合性和可读性;
    • 使用丰富的操作符词汇操作数据流;
    • 在订阅数据流之前什么也不会发生(延时计算);
    • 背压(backpressure)或消费者向生产者发送发射速率过快的信号的能力;
    • 与并发无关的高级抽象;

    可组合性和可读性

    可组合性指的是编排、协调多个异步任务的能力。包括使用先前任务的结果为后续任务提供输入,或者以fork-join格式执行多个任务以及在更高级别的系统中将异步任务作为独立组件重用。

    编排任务的能力与代码的可读性和可维护性是紧密相关的。随着异步处理的数量和复杂性的增加,编写和阅读代码变得越来越困难。正如我们所看到的,回调模式很简单,但是它的一个主要缺点是,对于复杂的任务,你需要从回调中执行回调,回调本身嵌套在另一个回调中,等等。这种混乱被称为回调地狱。可以想象,这样的代码很难回头进行推理。

    装配线类比

    你可以将在响应式应用中处理数据想象成(数据)在装配线上移动。响应式编程既是传送带,又是工作站。原材料从一个数据源(最初的Publisher)中倾泻而出,最终成为准备推送给消费者(Subscriber)的成品。

    原材料可以经过各种转换和中间步骤,或者成为将中间部件组装在一起的大型装配线的一部分。如果在某一点发生了小故障或者阻塞,受影响的工作站可以向上游发信号限制原材料的流动。

    操作符

    操作符就是装配线中的工作站。每一个操作符都向发布者(Publisher)添加新的行为,并将上一步中的发布者包装到一个新的实例中。整个链条就是这样连接在一起的,数据源自第一个发布者(Publisher),并沿着链条向下移动,在每个链接处被转换。最终,一个订阅者(Subscriber)结束这个流程。

    订阅前什么也不会发生

    在Reactor中,当你编写一个发布者(Publiser)链时,默认情况下不会开始向其中注入数据。相反,你创建的是一个异步处理的抽象描述(这有助于重用性和组合)。

    通过订阅操作(Subscribe()),你将发布者绑定到一个订阅者,从而触发整个链中的数据流。这是通过订阅者(Subscriber)发出一个请求(request())信号在内部实现的,该信号向上游传播,一直到源头发布者(Publisher)。

    背压

    向上游传播信号也被用来实现背压。在装配线类比中,我们将其描述为当工作站处理速度比上游工作站慢时,沿装配线向上游发送的反馈信号。

    响应式流规范中定义的真正的机制与装配线类比非常相似:订阅者可以在无限制的模式下工作,并让数据源以最快的速度推送数据;或者它可以用request()机制向数据源发出信号,表明自己最多可以处理n个数据。

    中间操作符还可以在传输过程中更改请求。假设有一个buffer操作符以10个元素为一个批次对元素进行分组。如果订阅者请求1个缓冲区,数据源就要生成10个元素。一些操作符还实现预取(prefetching)策略,这避免了每次请求一个元素的往返开销,如果在被请求之前生成元素的成本不是太高,那么这样做是有益的。

    预取策略将推模型转换为推-拉混合模型,在这种混合模型中,下游可以从上游拉出n个元素(如果它们已经可用)。但是,如果元素还没有准备好,它们会在生产好之后由上游推给下游。

    热响应式序列和冷响应式序列

    在响应式编程库的Rx家族中,我们可以区分两大类响应式序列:热响应式序列和冷响应式序列 。这种区别主要与响应式流如何对订阅者做出响应有关:

    • 冷响应式序列对每个订阅者(包括数据源)会重新启动一个全新的响应序列。
    • 热响应式序列对每个订阅者不会重零开始。相反,后来的订阅者只能接收到他们订阅后发出的数据。但是,请注意,一些热响应式序列可以缓存或回放全部或部分数据发布历史。从一般的角度来看,热序列甚至可以在没有订阅者在监听时发射数据(“订阅前什么都不会发生”规则的一个例外)。
    展开全文
  • (1)什么是响应式编程——响应式Spring的道法术器

    万次阅读 多人点赞 2018-03-06 10:54:22
    在开始讨论响应式编程(Reactive Programming)之前,先来看一个我们经常使用的一款堪称“响应式典范”的强大的生产力工具——电子表格。 举个简单的例子,某电商网站正在搞促销活动,任何单品都可以参加“满199减...

    本系列其他文章见:《响应式Spring的道法术器》

    响应式编程之道

    1.1 什么是响应式编程?

    在开始讨论响应式编程(Reactive Programming)之前,先来看一个我们经常使用的一款堪称“响应式典范”的强大的生产力工具——电子表格。

    举个简单的例子,某电商网站正在搞促销活动,任何单品都可以参加“满199减40”的活动,而且“满500包邮”。吃货小明有选择障碍(当然主要原因还是一个字:穷),他有个习惯,就是先在Excel上根据预算算好自己要买的东西:

    相信大家都用过Excel中的公式,这是一个统计购物车商品和订单应付金额的表格,其中涉及到一些公式:

    上图中蓝色的线是公式的引用关系,从中可以看出,“商品金额”是通过“单价x数量”得到的,“满199减40”会判断该商品金额是否满199并根据情况减掉40,右侧“订单总金额”是“满199减40”这一列的和,“邮费”会根据订单总金额计算,“最终应付款”就是订单总金额加上邮费。

    1.1.1 变化传递(propagation of change)

    为什么说电子表格软件是“响应式典范”呢,因为“单价”和“数量”的任何变动,都会被引用(“监听”)它的单元格实时更新计算结果,如果还有图表或数据透视图引用了这块数据,那么也会相应变化,做到了实时响应。变化的时候甚至还有动画效果,用户体验一级棒!

    这是响应式的核心特点之一:变化传递(propagation of change)。一个单元格变化之后,会像多米诺骨牌一样,导致直接和间接引用它的其他单元格均发生相应变化。

    看到这里,你可能会说,“切~ 不就是算付款金额吗,购物网站上都有这个最基础不过的功能啊”,这就“响应式”啦?但凡一个与用户交互的系统都得“响应”用户交互啊

    但是在响应式编程中,基于“变化传递”的特点,触发响应的主体发生了变化。假设购物车管理和订单付款是两个不同的模块,或者至少是两个不同的类——CartInvoice。也许我们的代码是这样的:

    Product.java(假设商品有两个属性nameprice,简单起见,price就不用BigDecimal类型了)

    public class Product {
        private String name;
        private double price;
        // 构造方法、getters、setters
    }
    

    Cart模块中:

    import com.example.Invoice; // 2
    
    public class Cart {
        ...
        public boolean addProduct(Product product, int quantity) {
            ...
            double figure = product.getPrice() * quantity;
            invoice.update(figure); // 1
            ...
        }
        ...
    }
    
    1. 是由Cart的对象去调用Invoice对象的更新订单金额的方法;
    2. Cart的代码中需要import Invoice

    而我们再观察这个Excel,发现“订单总金额”的计算公式不仅位于自己的单元格中,而且这个公式能主动监听和响应购物车数据的变化事件。对于购物车来说,它没有对订单付款方面的任何公式引用。感觉就像这样:

    假设数据流有操作的商品product和变化个数quantity两个属性:

    public class CartEvent {
        private Product product;
        private int quantity;
        // 构造方法、getters、setters
    }
    

    Invoice模块中:

    import com.example.Cart // 2
    
    public class Invoice {
        ...
        public Invoice(Cart cart) {
            ...
            this.listenOn(cart);    // 1
            ...
        }
        // 回调方法
        public void onCartChange(CartEvent event) {
            ...
        }
        ...
    }
    
    1. 是由Invoice的对象在初始化的时候就声明了对Cart对象的监听,从而一旦Cart对象有响应的事件(比如添加商品)发生的时候,Invoice就会响应;
    2. Invoice的代码中import Cart

    做过Java桌面开发的朋友可能会想到Java swing中的各种监听器,比如MouseListener能够监听鼠标的操作,并实时做出响应。所以C/S的客户端总是比B/S的Web界面更具有响应性嘛。

    所以,这里我们说的是一种生产者只负责生成并发出数据/事件,消费者来监听并负责定义如何处理数据/事件的变化传递方式

    那么,Cart对象如何在发生变化的时候“发出”数据或事件呢?

    1.1.2 数据流(data stream)

    这些数据/事件在响应式编程里会以数据流的形式发出。

    我们再观察一下购物车,这里有若干商品,小明每次往购物车里添加或移除一种商品,或调整商品的购买数量,这种事件都会像过电一样流过这由公式串起来的多米诺骨牌一次。这一次一次的操作事件连起来就是一串数据流(data stream),如果我们能够及时对数据流的每一个事件做出响应,会有效提高系统的响应水平。这是响应式的另一个核心特点:基于数据流(data stream)

    如下图是小明选购商品的过程,为了既不超预算,又能省邮费,有时加有时减:

    这一次一次的操作就构成了一串数据流。Invoice模块中的代码可能是这样:

        public Invoice(Cart cart) {
            ...
            this.listenOn(cart.eventStream());  // 1
            ...
        }
    
    1. 其中,cart.eventStream()是要监听的购物车的操作事件数据流,listenOn方法能够对数据流中到来的元素依次进行处理。

    1.1.3 声明式(declarative)

    我们再到listenOn方法去看一下:

    Invoice模块中,上边的一串公式被组装成如下的伪代码:

        public void listenOn(DataStream<CartEvent> cartEventStream) {   // 1
            double sum = 0;
            double total = cartEventStream
                // 分别计算商品金额
                .map(cartEvent -> cartEvent.getProduct().getPrice() * cartEvent.getQuantity())  // 2
                // 计算满减后的商品金额
                .map(v -> (v > 199) ? (v - 40) : v)
                // 将金额的变化累加到sum
                .map(v -> {sum += v; return sum;})
                // 根据sum判断是否免邮,得到最终总付款金额
                .map(sum -> (sum > 500) ? sum : (sum + 50));
            ...
    
    1. cartEventStream是数据流,DataStream是某种数据流类型,可以暂时想象成类似在Java 8版本增加的对数据流进行处理的Stream API(下节会说到为啥不用Java Stream)。

    2. map方法用于对数据流中的元素进行映射,比如第一个将cartEvent中的商品价格和数量拿到,然后算出本次操作的金额;第二个判断是否能享受“满199减40”的活动。

    这里的伪代码用到了lambda,它非常适用于数据流的处理。没有接触过lambda的话没有关系,我们后续会再聊到它。

    这是一种**“声明式(declarative)”**的编程范式。通过四个串起来的map调用,我们先声明好了对于数据流“将会”进行什么样的处理,当有数据流过来时,就会按照声明好的处理流程逐个进行处理。

    比如对于第一个map操作:

    **声明式编程范式的威力在于以不变应万变。**无论到来的元素是什么,计算逻辑是不变的,从而形成了一种对计算逻辑的“绑定”。

    再举个简单的例子方便理解:

    a = 1;
    b = a + 1;
    a = 2;
    

    这个时候,b是多少呢?在Java以及多数语言中,b的结果是2,第二次对a的赋值并不会影响b的值。

    假设Java引入了一种新的赋值方式:=,表示一种对a的绑定关系,如

    a = 1;
    b := a + 1;
    a = 2;
    

    由于b保存的不是某次计算的值,而是针对a的一种绑定关系,所以b能够随时根据a的值的变化而变化,这时候b==3,我们就可以说:=是一种声明式赋值方式。而普通的=是一种命令式赋值方式。事实上,我们绝大多数的开发都是命令式的,如果需要用命令式编程表达类似上边的这种绑定关系,在每次a发生变化并需要拿到b的时候都得执行b = a + 1来更新b的值。

    如此想来,“绑定美元政策”不也是一种声明式的范式吗~

    总结来说,命令式是面向过程的,声明式是面向结构的

    不过命令式和声明式本身并无高低之分,只是声明式比较适合基于流的处理方式。这是响应式的第三个核心特点:声明式(declarative)。结合“变化传递”的特点,声明式能够让基于数据流的开发更加友好。

    1.1.4 总结

    总结起来,响应式编程(reactive programming)是一种基于数据流(data stream)和变化传递(propagation of change)的声明式(declarative)的编程范式。

    响应式编程的“变化传递”就相当于果汁流水线的管道;在入口放进橙子,出来的就是橙汁;放西瓜,出来的就是西瓜汁,橙子和西瓜、以及机器中的果肉果汁以及残渣等,都是流动的“数据流”;管道的图纸是用“声明式”的语言表示的。

    这种编程范式如何让Web应用更加“reactive”呢?

    我们设想这样一种场景,我们从底层数据库驱动,经过持久层、服务层、MVC层中的model,到用户的前端界面的元素,全部都采用声明式的编程范式,从而搭建一条能够传递变化的管道,这样我们只要更新一下数据库中的数据,用户的界面上就相应的发生变化,岂不美哉?尤其重要的是,一处发生变化,我们不需要各种命令式的调用来传递这种变化,而是由搭建好的“流水线”自动传递。

    这种场景用在哪呢?比如一个日志监控系统,我们的前端页面将不再需要通过“命令式”的轮询的方式不断向服务器请求数据然后进行更新,而是在建立好通道之后,数据流从系统源源不断流向页面,从而展现实时的指标变化曲线;再比如一个社交平台,朋友的动态、点赞和留言不是手动刷出来的,而是当后台数据变化的时候自动体现到界面上的。

    具体如何来实现呢,请看下一节关于响应式流的介绍。

    展开全文
  • Spring 5.0 中发布了重量级组件 Webflux,拉起了响应式编程的规模使用序幕。WebFlux 使用场景是异步非阻塞的,使用 Webflux 作为系统解决方案,在大多数场景下可以提高系统吞吐量。Spring Boot 2.0 是基于 Spring5...
    106e3e674fbfa37955660909aae07dae.png

    Spring 5.0 中发布了重量级组件 Webflux,拉起了响应式编程的规模使用序幕。

    WebFlux 使用的场景是异步非阻塞的,使用 Webflux 作为系统解决方案,在大多数场景下可以提高系统吞吐量。Spring Boot 2.0 是基于 Spring5 构建而成,因此 Spring Boot 2.X 将自动继承了 Webflux 组件,本篇给大家介绍如何在 Spring Boot 中使用 Webflux 。

    为了方便大家理解,我们先来了解几个概念。

    响应式编程

    在计算机中,响应式编程或反应式编程(英语:Reactive programming)是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。

    例如,在命令式编程环境中,a=b+c 表示将表达式的结果赋给 a,而之后改变 b 或 c 的值不会影响 a 。但在响应式编程中,a 的值会随着 b 或 c 的更新而更新。

    响应式编程是基于异步和事件驱动的非阻塞程序,只需要在程序内启动少量线程扩展,而不是水平通过集群扩展。

    用大白话讲,我们以前编写的大部分都是阻塞类的程序,当一个请求过来时任务会被阻塞,直到这个任务完成后再返回给前端;响应式编程接到请求后只是提交了一个请求给后端,后端会再安排另外的线程去执行任务,当任务执行完成后再异步通知到前端。

    Reactor

    Java 领域的响应式编程库中,最有名的算是 Reactor 了。Reactor 也是 Spring 5 中反应式编程的基础,Webflux 依赖 Reactor 而构建。

    Reactor 是一个基于 JVM 之上的异步应用基础库。为 Java 、Groovy 和其他 JVM 语言提供了构建基于事件和数据驱动应用的抽象库。Reactor 性能相当高,在最新的硬件平台上,使用无堵塞分发器每秒钟可处理 1500 万事件。

    简单说,Reactor 是一个轻量级 JVM 基础库,帮助你的服务或应用高效,异步地传递消息。Reactor 中有两个非常重要的概念 Flux 和 Mono 。

    Flux 和 Mono

    Flux 和 Mono 是 Reactor 中的两个基本概念。Flux 表示的是包含 0 到 N 个元素的异步序列。在该序列中可以包含三种不同类型的消息通知:正常的包含元素的消息、序列结束的消息和序列出错的消息。当消息通知产生时,订阅者中对应的方法 onNext(), onComplete()和 onError()会被调用。

    Mono 表示的是包含 0 或者 1 个元素的异步序列。该序列中同样可以包含与 Flux 相同的三种类型的消息通知。Flux 和 Mono 之间可以进行转换。对一个 Flux 序列进行计数操作,得到的结果是一个 Mono对象。把两个 Mono 序列合并在一起,得到的是一个 Flux 对象。

    WebFlux 是什么?

    WebFlux 模块的名称是 spring-webflux,名称中的 Flux 来源于 Reactor 中的类 Flux。Spring webflux 有一个全新的非堵塞的函数式 Reactive Web 框架,可以用来构建异步的、非堵塞的、事件驱动的服务,在伸缩性方面表现非常好。

    非阻塞的关键预期好处是能够以小的固定数量的线程和较少的内存进行扩展。在服务器端 WebFlux 支持2种不同的编程模型:

    • 基于注解的 @Controller 和其他注解也支持 Spring MVC
    • Functional 、Java 8 lambda 风格的路由和处理
    c84b52fc6661c5fedd9e3138963e4279.png

    如图所示,WebFlux 模块从上到下依次是 Router Functions、WebFlux、Reactive Streams 三个新组件。

    • Router Functions 对标准的 @Controller,@RequestMapping 等的 Spring MVC 注解,提供一套 函数式风格的 API,用于创建 Router、Handler 和Filter。
    • WebFlux 核心组件,协调上下游各个组件提供 响应式编程 支持。
    • Reactive Streams 一种支持 背压 (Backpressure) 的 异步数据流处理标准,主流实现有 RxJava 和 Reactor,Spring WebFlux 集成的是 Reactor。

    默认情况下,Spring Boot 2 使用 Netty WebFlux,因为 Netty 在异步非阻塞空间中被广泛使用,异步非阻塞连接可以节省更多的资源,提供更高的响应度。通过比较 Servlet 3.1 非阻塞 I / O 没有太多的使用,因为使用它的成本比较高,Spring WebFlux 打开了一条实用的通路。

    值得注意的是:支持 reactive 编程的数据库只有 MongoDB, redis, Cassandra, Couchbase

    Spring Webflux

    Spring Boot 2.0 包括一个新的 spring-webflux 模块。该模块包含对响应式 HTTP 和 WebSocket 客户端的支持,以及对 REST,HTML 和 WebSocket 交互等程序的支持。一般来说,Spring MVC 用于同步处理,Spring Webflux 用于异步处理。

    Spring Boot Webflux 有两种编程模型实现,一种类似 Spring MVC 注解方式,另一种是基于 Reactor 的响应式方式。

    快速上手

    添加 webflux 依赖

    org.springframework.boot

    spring-boot-starter-webflux

    63c9cc12f514ee34bdb5d6abd7e8b113.png

    通过 IEDA 的依赖关系图我们可以发现spring-boot-starter-webflux依赖于spring-webflux、Reactor 和 Netty 相关依赖包。

    创建 Controller

    @RestController

    public class HelloController {

    @GetMapping("/hello")

    public Mono hello() {

    return Mono.just("Welcome to reactive world ~");

    }

    }

    通过上面的示例可以发现,开发模式和之前 Spring Mvc 的模式差别不是很大,只是在方法的返回值上有所区别。

    • just() 方法可以指定序列中包含的全部元素。
    • 响应式编程的返回值必须是 Flux 或者 Mono ,两者之间可以相互转换。

    测试类

    @RunWith(SpringRunner.class)

    @WebFluxTest(controllers = HelloController.class)

    public class HelloTests {

    @Autowired

    WebTestClient client;

    @Test

    public void getHello() {

    client.get().uri("/hello").exchange().expectStatus().isOk();

    }

    }

    运行测试类,测试用例通过表示服务正常。启动项目后,访问地址:http://localhost:8080/hello,页面返回信息:

    Welcome to reactive world ~

    证明 Webflux 集成成功。

    以上便是 Spring Boot 集成 Webflux 最简单的 Demo ,后续我们继续研究 Webflux 的使用。

    展开全文
  • 谈谈响应式编程

    千次阅读 2016-10-31 11:33:52
    随着前端框架react,angular以及vue的流行,响应式编程也开始在前端领域得以广泛应用。因此,了解并且理解响应式编程有助于更好地学习这些框架,同时利用好响应式编程的相关工具,可以让编程更加轻松。 什么是响应式...

    随着前端框架react,angular以及vue的流行,响应式编程也开始在前端领域得以广泛应用。因此,了解并且理解响应式编程有助于更好地学习这些框架,同时利用好响应式编程的相关工具,可以让编程更加轻松。

    什么是响应式编程

    和平常经常听说的面向对象编程和函数式编程一样,响应式编程(Reactive Programming)就是一个编程范式,但是与其他编程范式不同的是它是基于数据流和变化传播的。我们经常在程序中这样写

    A = B + C

    A被赋值为BC的值。这时,如果我们改变B的值,A的值并不会随之改变。而如果我们运用一种机制,当B或者C的值发现变化的时候,A的值也随之改变,这样就实现了”响应式“。

    而响应式编程的提出,其目的就是简化类似的操作,因此它在用户界面编程领域以及基于实时系统的动画方面都有广泛的应用。另一方面,在处理嵌套回调的异步事件,复杂的列表过滤和变换的时候也都有良好的表现。


    函数响应式编程

    而主要利用函数式编程(Functional Programming)的思想和方法(函数、高阶函数)来支持Reactive Programming就是所谓的Functional Reactive Programming,简称FRP。

    FPR 将输入分为两个基础的部分:行为(behavior)和事件(events) 。这两个基本元素在函数响应式编程中都是第一类(first-class)值。 其中行为是随时间连续变化的数据,而事件则是基于离散的时间序列 。例如:在我们操作网页的时候,会触发很多的事件,包括点击,拖动,按键事件等。这些事件都是不连续的。对事件求值是没有意义的,所有我们一般要通过fromEventbuffer等将其变成连续的行为来做进一步处理。与RP相比,FRP更偏重于底层。由于采用了函数式编程范式,FRP也自然而然带有其特点。这其中包括了不可变性,没有副作用以及通过组合函数来构建程序等特点。

    应用范围

    1. 多线程,时间处理,阻塞等场景
    2. ajax,websocket和数据加载
    3. 失败处理
    4. DOM事件和动画

    展开全文
  • 响应式编程在Android中的应用

    千次阅读 2020-08-13 01:46:20
    响应式编程简介 响应式编程的具体实现-RxJava 基本概念 RxJava的四种角色 热Observable和冷Observable Observable创建符 Subject 直接创建 Observable 从列表创建 Observable 具有特殊功能的创建符 过滤Observables ...
  • 函数式编程和响应式编程

    万次阅读 2017-06-12 21:37:57
    响应式编程目标就是,如果b或者c的数值发生变化,a的数值会同时发生变化。函数式编程函数式编程是一系列被不公平对待的编程思想的保护伞,它的核心思想是,它是一种将程序看成是数学方法的求值、不会改变状态、不会...
  • Sping5——响应式编程

    2019-05-10 11:46:14
    1、响应式编程基础 1.1、什么是响应式编程响应式编程是一种面向数据流和变化传播的编程范式。 使用它可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。...
  • java异步响应式编程

    千次阅读 2018-03-24 22:46:50
    响应式编程是一种怎样编程的套路,是一种特殊场景的代码优化. Remote资源 a.查询一个去过的地点 b.查询推荐的目标地点 c.预测目标地点天气 d.计算推荐地点路线信息 a和b没有依赖关系,所以我们可以同时取两个...
  • Flutter的响应式编程

    2019-09-05 20:23:44
    我们可能都听说过响应式编程这个名词,但什么是响应式编程呢?我们先看看维基百科上的定义: 这里面有很多的名词,像declarative programming paradigm(声明式编程范式),imperative programming paradigm(指令式...
  • 响应式编程(reactive programming)是一种基于数据流(data stream)和变化传递(propagation of change)的声明式(declarative)的编程范式。 响应式编程会声明数据变化对应的操作逻辑(声明式),会监听数据...
  • Spring5.0响应式编程入门

    万次阅读 2018-06-14 09:35:29
    引言​ 响应式编程是一种面向数据流和变化传播的编程范式。使用它可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。我们可以使用声明的方式构建应用程序的...
  • Scala Reactive Programming 响应式编程 Functional Reactive Programming (FRP), we will first understand the meaning of Reactive and Reactive programming in this section. 什么是响应? 反应意味着及时对...
  • 函数式编程 防御式编程 响应式编程 契约式编程
  • 在Cocoa框架下的的函数响应式编程框架。Github mac客户端产物,富含cocoa框架多种组件,提供基于时间变化的数据流的组合和变换。命令式编程vs函数式响应式编程 命令式编程用语言提供的操作命令编写操作序列给电脑...
  • 命令式编程与响应式编程 消息驱动 观察者模式 Tomcat的NIO异步网络io 服务器推技术 Servlet3.0与3.1 本节内容 响应式系统主流框架概览 akka 使用Scala语言开发,后期支持Java,但是在Java社区并不如从前受欢迎 ...
  • 响应式编程就是利用异步数据流进行编程,本质上就是观察者(Observer)模式的一种表现形式。我们首先讨论实现异步操作的几种常见方式,然后引出响应式编程的主流实现技术。 1. 实现异步的常见方式 在Java中,为了...
  • 响应式编程学习

    2019-12-29 14:46:02
    响应式宣言 We want systems that are Responsive, Resilient, Elastic and Message Driven. 四个关键字: Responsive:即时响应性,系统尽可能及时响应。 Resilient:回弹性,系统在出现故障时保持响应。通过复制...
  • 响应式编程 Reactive Programming 响应式编程是一种异步编程范式,涉及数据流和变化的传播。 这意味着可以通过所使用的编程语言轻松地表示静态(例如数组)或动态(例如事件发射器)数据流。 作为向响应式编程方向迈出的...
  • 响应式编程简介之:Reactor

    万次阅读 2020-11-06 09:12:47
    Reactor是reactivex家族的一个非常重要的成员,Reactor是第四代的reactive library,它是基于Reactive Streams标准基础上开发的,主要用来构建JVM环境下的非阻塞应用程序。 今天给大家介绍一下Reactor。
  • SpringBoot2.0响应式编程

    2020-08-02 16:23:38
    简介:讲解什么是reactive响应式编程使用的好处 1、基础理解: 依赖于事件,事件驱动(Event-driven) 一系列事件称为“流” 异步 非阻塞 观察者模式 网上的一个例子: int b= 2; int c=3 int a = b+c //...
  • 响应式编程中的Flux和Mono

    万次阅读 多人点赞 2019-04-22 21:46:43
    响应式编程介绍 反应式编程来源于数据流和变化的传播,意味着由底层的执行模型负责通过数据流来自动传播变化。比如求值一个简单的表达式 c=a+b,当 a 或者 b 的值发生变化时,传统的编程范式需要对 a+b 进行重新计算...
  • RxSwift 函数式编程/响应式编程

    千次阅读 2018-07-23 10:04:20
    函数式编程和响应式编程 RxSwift使用教程 监听相关 添加监听 RxSwift的核心是想是 Observable sequence,Observable表示可监听或者可观察,也就是说RxSwift的核心思想是可监听的序列。并且,Observable ...
  • RxJava 响应式编程初探

    2018-05-06 17:58:09
    最近在学习Spring Cloud Hystrix框架,发现里面的代码写法跟传统的编程思路很不一样,充满了回调和Lamda风格,于是去深入了解了一下,这便是本文的主题 RxJava 响应式编程。 RxJava 我们一般写的程序,以流程为...
  • 响应式编程总览

    2018-07-03 14:41:38
    1 响应式编程总览In computing, reactive programming is an asynchronous programming paradigm concerned with data streams and the propagation of change. - Reactive programming - Wikipedia在上述响应式...
  • 响应式编程 RxJava系列

    万次阅读 2019-04-26 20:46:42
    一方面反映出现在的高级开发者的追求越来越高逼格,另一方面也反映从从结构化编程到面向对象编程到函数式编程的发展历程,越来越多的应用和面试中都会有ReactiveX,响应式编程中RxJava可谓如鱼得水。 最近也一直在...
  • WebFlux 学习(1)响应式编程简介

    千次阅读 2018-04-27 16:10:22
    在传统的命令式编程模式,程序都是按照人工编写的指令(一般情况下,...那么,什么是响应式编程呢?这里引用 wikipedia 上的解释,比较抽象,所以我决定一边使用,一边学习,并一边分享给大家。 响应式编程是就是对于
  • 理解java响应式编程

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 57,393
精华内容 22,957
关键字:

响应式编程应用场景