反应式编程与事件驱动编程有何不同?

Nar*_*sty 36 javascript event-driven frp reactive-programming bacon.js

我正在学习JavaScript中的反应式编程和功能反应式编程.我很迷茫.

维基百科说,有各种方法来编写反应性代码,如命令式,OORP和功能性.我想知道事件驱动是否只是编写反应代码的另一种方式?

响应式编程如何与Promises相关?我认为承诺是事件驱动和回调地狱的替代品.

Fra*_*yce 74

反应式编程与事件驱动编程有何不同?

事件驱动的编程围绕着所谓的事件,这些事件是在事情发生时编程"触发"的抽象事物.代码中的其他位置"监听"事件并响应事件发生时他们需要做的事情.例如,事件可以是"用户按下此按钮"或"打印机已完成打印文档".

反应式编程处理数据.最终,这是事件驱动编程的特例.事件:数据已更改.事件处理程序:更改一些更多数据(如果适用).当您想到电子表格时,通常会清除此概念.如果你设置cell1 = cell2 + cell3它隐含地设置两个事件处理程序的数据更改事件cell2cell3更新cell1的数据. cell1的数据没有这样的事件处理程序,因为没有单元格依赖于它的值.


TL; DR;

维基百科说,有各种方法来编写反应性代码,如命令式,OORP和功能性.我想知道事件驱动是否只是编写反应代码的另一种方式?

事件驱动编程的想法与命令式与OO与功能性的概念正交.

  • Imperitive编程:专注于改变程序的状态将实现您想要的.大多数计算机都是必要的(与声明性编程相反),而更高级别的语言有时是声明性的.相反,声明性编程处理的是编写代码,指定您希望它执行的操作,而不是您希望代码执行操作的方式.
  • Ø bject Ø riented编程:所谓的对象,或者与相关方法的数据包协议.与函数式编程不同,因为这些方法能够访问与对象关联的数据.
  • 功能编程:处理可重复使用的功能,或处理输入和输出的程序.这与OO编程不同,因为传统上函数不具有将数据与输入和输出之外的函数相关联的能力.

事件驱动编程:构建程序以处理("处理")程序中发生的其他事件("事件").换句话说,它在逻辑上构建您的代码

When Event1 happens
    do A and B

When Event2 happens
    do B and C
Run Code Online (Sandbox Code Playgroud)

但是有很多方法可以编写这个代码,实际上有很多方法可以编写代码,有很多方法可以在功能上编写代码等等.但是这里有一些例子.

势在必行(使用事件循环):

while(true)
    // some other code that you need to do...

    if Event1 then
        do A
        do B
    if Event2 then
        do B
        do C
Run Code Online (Sandbox Code Playgroud)

面向对象(带后台线程):

// event queue
events = new EventQueue()

handler = new EventHandler()
// creates background thread
Thread.DoInBackground(handler.listenForEvents(events))

// ... other code ...

// fire an event!
events.enqueue(new Event1())

// other file
class EventHandler
    Func listenForEvents(events)
        while(true)
            while events.count > 0
                newEvent = event.dequeue()
                this.handleEvent(newEvent)
            Thread.Sleep(Time.Seconds(1))

    Func handleEvent(event)
        if event is Event1
            this.A()
            this.B()
        if event is Event2
            this.B()
            this.C()

    Func A()
        // do stuff
        return

    Func B()
        // do stuff
        return

    Func C()
        // do stuff
        return
Run Code Online (Sandbox Code Playgroud)

功能(对事件的语言支持)

on Event(1) do Event1Handler()
on Event(2) do Event2Handler()

Func Event1Handler()
    do A()
    do B()

Func Event2Handler()
    do B()
    do C()

Func A()
    // do stuff
    return

Func B()
    // do stuff
    return

Func C()
    // do stuff
    return

// ... some other code ...

// fire! ... some languages support features like this, and others have
// libraries with APIs that look a lot like this.
fire Event(1)
Run Code Online (Sandbox Code Playgroud)

响应式编程如何与Promises相关?

Promise是程序执行流程的抽象,可以总结如下:

  • 阿斯克:每当你做完你正在做的事情时,你会给我回电话吗?
  • 回答:当然,我保证

这里没什么特别的,除了它是另一种思考代码执行顺序的方法.例如,当您调用远程计算机时,promise很有用.有了承诺,你可以说"当你从这个远程呼叫返回时给我回电话!".无论您使用哪个库,都会承诺在从远程计算机返回某些内容时回拨您.通常,这很有用,因为它允许您在此期间执行其他操作而无需等待返回的调用.

打孔线:有很多不同风格的代码,但它们在事件驱动和反应式编程模式中不起太大作用.据我所知,您可以在大多数语言中进行事件驱动和/或反应式编程.

  • 总的来说,这篇文章是一本关于原则的好书。有关更多信息,请参阅:https://www.oreilly.com/ideas/reactive-programming-vs-reactive-systems (3认同)
  • 至关重要的是,Promise 不仅仅是一个执行流:它们是一个持久性模型,表示该执行的状态及其最终输出。因为它们是持久的,所以它们可以被存储、共享、引用、传递。然而,在纯粹的事件驱动系统中,如果您事后开始监听,您将缺乏历史记录,并且您(通常)必须监听所有事件,才能听到任何事件。Promise 使您能够封装和订阅有限的、单一用途的事件流,并且还可以在未来的任何时间检查该事件流的状态。 (2认同)
  • 我喜欢你的答案比公认的更好,但所有这一切似乎都归结为我们的行业似乎永远存在产生新流行语的需求。对我来说,您关于区分事件驱动编程和所谓的“反应式编程”的说法有些牵强。“反应式编程处理数据。归根结底,这是事件驱动编程的一个特例。” 我想,对于那些对事件的认识有限的人来说,这只是一个特例。不管怎样,贫血流行语必死无疑! (2认同)

Oll*_*liM 23

响应式编程如何与Promises相关?我认为这个承诺是事件驱动和回调地狱的替代品.

在实践中这两者是相关的,我喜欢称Promises为功能反应式编程的门户药物.

+----------------------+--------+-------------+
|                      |  Sync  |    Async    |
+----------------------+--------+-------------+
| Single value or null | Option | Promise     |
| Multiple values      | List   | EventStream |
+----------------------+--------+-------------+
Run Code Online (Sandbox Code Playgroud)

Promise可以被认为是带有一个项目的EventStreams,或者你可以将EventStreams视为多个Promise随着时间的推移.

Promise可以链接,接近响应式编程:

getUser() // return promise
   .then((userId) => {
       return fetch("/users/"+userId)
   })
   .then((user) => {
       alert("Fetched user: " + user.name)
   })
Run Code Online (Sandbox Code Playgroud)

与bacon.js相同:

const userStream = userIdStream // EventStream of userIds
   .flatMapLatest((userId) => {
       return Bacon.fromPromise(fetch("/users/"+userId))
   })
const userNameStream = userStream.map((user) => user.name)
userNameStream.onValue((user) => {
   alert("Fetched user: " + user.name)
})
Run Code Online (Sandbox Code Playgroud)

两个代码片段都做同样的事情,但思维方面存在很大差异:对于承诺,您正在考虑以明确的方式使用异步步骤处理单个操作 - 思维是必要的,您正在逐步完成工作.使用FRP,您会说" userIds通过应用这两个转换步骤从流中创建用户名流".如果您拥有一组用户名,而不关心他们来自何处,并说"只要有新用户名,请将其显示给用户".

FRP编码样式将指导您将问题建模为值流(即随时间变化的值)以及这些值之间的关系.如果您已经了解Promises,那么初始学习曲线会更容易一些,但只有当您开始思考并以不同方式对问题建模时才能获得主要好处 - 使用FRP库进行命令式编程是可能的(如果不是非常有用).


for*_*erg 7

差异主要与您如何“配置”(或声明)事物约定有关:当其他事情发生时,某些事情会发生什么。

在响应式编程中,您声明更改的反应。您不必预先预见该更改所需的这种反应,您可以在以后随时添加 -声明- 这种反应。因此,它可能被视为“拉动”或“观察”策略。

因此,在反应式编程中,您连接/监视您知道存在的数据。数据在这里至关重要。

示例:用户单击页面上的某个项目 -> 更新计数器用户单击的次数。

示例计算器应用程序:计算器显示屏绑定到所有按钮,并通过显示屏上的自身变化对任何更改(单击按钮)做出反应。按钮不知道它们的点击可以被任何其他部分利用。

在事件驱动编程中,您可以在命令式编写的代码中在特定情况下触发事件。您需要在此处预先明确,因为需要首先触发事件才能稍后接收 - 因为基本上您将事件推送到代码的“发生更改”部分。所以这是一个“推”策略。

因此,在事件驱动编程中,您在某种情况下推送一个事件,该事件可能会被代码的其他部分接收。这里情况很重要,数据并不重要。

示例:某人访问了联系页面 -> 触发一个事件(最终可能不会被任何侦听器接收到,这是许多模块和库的典型情况)。

计算器应用程序示例:计算器显示屏只是一个侦听器,按钮会触发事件。按钮需要知道它们存在于特定的上下文中(但是 - 由于事件侦听器模式 - 不必知道该上下文到底是什么),因此它们需要触发事件。

所以在大多数情况下,它们只是不同的约定。看这个简单的例子。命令式方法示例:

event: perform some operation on a, e.g. a += value, and trigger the event
listener: counter++
Run Code Online (Sandbox Code Playgroud)

以及反应式声明方法示例:

counter: whenever an operation on a occurs, react with this: counter++
Run Code Online (Sandbox Code Playgroud)

在最后一个例子中不需要触发任何东西 - 你只需“连接”对可能发生的任何事情的反应。

那么,您可能会说,反应必然是a反应性方法,而在命令式事件驱动方法中,您推送一个稍后可以由侦听器接收的事件 - 并且由于这种类型的方法与数据没有任何关系,您可以稍后将其更改a += value为其他任何内容,甚至a完全删除。

事件驱动方法本质上与数据无关。反应式编程基本上与数据有关。

正如您所看到的,反应式编程是面向数据的(数据的变化会触发其他代码做出反应),而事件驱动的编程是面向过程的(数据是否变化以及什么变化并不重要,如果有的话 - 你只需触发一个代码的其他部分将收到的事件)。在后一种情况下,您需要知道需要“通知”代码的其他部分,并且您必须预见应该触发该事件。在前一种情况下,你不必这样做,你可以随时这样做,或者根本不这样做 - 不需要触发事件 - 但这里的技巧是,必须有一个你可以连接的“东西”你的反应声明,一种观察者,可以让你对观察到的变化做出反应。