使用promises进行一次事件处理?

Fre*_*dyC 11 javascript events publish-subscribe promise

通常的场景.我希望有一些解耦的代码,即在某些东西准备就绪时触发事件.对于整个应用程序运行,这只会发生一次.

另一方面,还有另一段代码,我想在触发两个或多个事件时发生其他事情.我的意思是像所有这些,如依赖.

好吧,更多异步的东西在一起...绝对承诺对吗?

然后我开始思考.使用pub/sub进行一次性活动真的很明智吗?仅仅制定可接受的承诺,一旦该事件即将被触发,就会解决这个问题会更好吗?但是,这意味着我需要将解耦代码相互连接起来.有一件事是共享EventEmitter,但依赖于某些代码来实际创建承诺...听起来相当糟糕.

所以我在考虑某种混合.有模块,其他模块可以通过它的名称请求"事件"并获得准备好的Promise对象.然后,其他模块应该触发该事件并以这种方式有效地完成/拒绝该事件.

var promisedLand = require('./promisedLand');
promisedLand.waitFor('event'); // returns promise
promisedLand.resolve('event', value);
promisedLand.reject('event', error);
Run Code Online (Sandbox Code Playgroud)

您对此解决方案有何看法?有机会有这样的解决方案吗?

Ben*_*aum 24

好问题.让我从一件事开始:承诺不是事件发射器.

让我重申一下,因为这是一个误解而来的很多.承诺不是事件发射器.随着进展,他们可以被黑客攻击成一种残缺的事件发射器,但在一天结束时.承诺不是事件发射器.

承诺

这些是什么?Promise是一个值的"框",您可以使用该.then方法在某个时刻打开该值,然后将结果放在另一个框中.没有更多,没有更少.

就像你说的,承诺是一次.如果您的活动是一次性活动 - 那么承诺绝对可以.从本质上讲,您的活动是一种可能性,并且承诺在大多数情况下对其进行更好的建模.

承诺作为排放者

使用promises作为事件发射器的问题是组合,promises中的进展事件根本不能很好地构成.承诺链和组合以及事件都没有.这就是为什么Q库倾向于推进v2中的估计.这就是为什么进展从未包含在ECMAScript 6中的原因.

事件发射器本身就是一个非常精细的抽象,当它们是建立关系(pub-sub)的正确工具时使用事件发射器,当它们是建立关系的正确工具时使用promises,当它们使用流时使用它们是建立关系模型的合适工具.只是不要使用一个工具,因为这(从经验)将带给你除了很多痛苦.

我在我的问题中描述的内容真的很酷,那又怎么样?

你在找什么?哦,那存在.虽然它也有自己的问题,但它实际上非常精彩.

您正在寻找的是FRP - 功能性反应式编程.有很多图书馆用最好的一个(在我看来)是BaconJS.

FRP有你正在谈论的可观察的概念.以下是BaconJS网站上的计数器示例:

var up   = $('#up').asEventStream('click');
var down = $('#down').asEventStream('click');

var counter =
  // map up to 1, down to -1
  up.map(1).merge(down.map(-1))
  // accumulate sum
    .scan(0, function(x,y) { return x + y });

// assign observable value to jQuery property text
counter.assign($('#counter'), 'text');
Run Code Online (Sandbox Code Playgroud)

非常类似于链接中的承诺,但不代表直接延续,而是连续流和汇.

FRP是Haskell等函数式语言中非常常见和发展的范例,非常适用于JavaScript.这不是很常见它有自己的缺点,但它肯定觉得像你脑子里想的是什么.

所以,简短的回顾:

  • 承诺不是事件发射器.Promise非常棒,并且可以解决许多有趣的并发问题 - 但它们并不是所有解耦流控制的灵丹妙药.
  • FRP是你提出的这个很酷的东西,但还没有制定.它具有完全如您在问题中描述的可观察和事件的概念.

此外,你可以自己拍拍自己,在不知道自己的情况下思考范式.你应得的,老实说.


Fre*_*dyC 2

好吧,我已经制定了自己的解决方案,类似于问题中提出的解决方案。

欢迎来到应许之地