触发事件触发事件
我的整个项目使用(蓝鸟)承诺,但有一个使用EventEmitter的特定图书馆。
我想实现这样的事情:
Promise.on('connect', function() { x.doSomething(); }).then(function() { return new Promise(function(resolve) { y.doAction(resolve); // this will result in `eventB` getting emitted }); }).on('eventB', function() { z.handleEventB(); }).then(function() { z.doSomethingElse(); });
我在Promises链的中间读到了EventEmitter的答案。 这给了我一个方法来执行“连接”事件的callback。 这是我到目前为止的地方
var p = new Promise(function(resolve) { emitter.on('connect', resolve); }); p.on = function() { emitter.on.apply(emitter, arguments); return p; }; p.on('connect', function() { x.doSomething(); }).then(function() { return new Promise(function(resolve) { y.doAction(resolve); // this will result in eventB getting emitted }); });
现在如何进一步链接“eventB”?
我假设你想为每个事件做不同的事情。 即使eventB
是由connect
动作触发的,你可以把它看作另一个逻辑stream。
注意:为避免您和其他需要阅读这个代码库的人混淆,我build议不要用其他方法来补充promise,除非您对文档进行了非常全面的介绍。
从你的例子来看,似乎下面的工作。
var Promise = require( 'bluebird' ) var emitter = someEmitter() var connected = new Promise( function( resolve ){ emitter.on( 'connect', resolve ) }) var eventBHappened = new Promise( function( resolve ){ emitter.on( 'eventB', resolve ) }) connected.then( function(){ x.doSomething() }).then( function(){ y.doSomethingElse() // will trigger `eventB` eventually }) // this promise stream will begin once `eventB` has been triggered eventBHappened.then( function(){ z.doSomething() })
如果你想简化这个常数
var p = new Promise( function( resolve ){ emitter.on( 'something', resolve ) })
你可以使用这样的东西
function waitForEvent( emitter, eventType ){ return new Promise( function( resolve ){ emitter.on( eventType, resolve ) }) }
上面的代码解决scheme转化为
var Promise = require( 'bluebird' ) var emitter = someEmitter() function waitForEvent( eventEmitter, eventType ){ return new Promise( function( resolve ){ eventEmitter.on( eventType, resolve ) }) } waitForEvent( emitter, 'connect' ).then( function(){ x.doSomething() }).then( function(){ y.doSomethingElse() // will trigger `eventB` eventually }) // this promise stream will begin once `eventB` has been triggered waitForEvent( emitter, 'eventB' ).then( function(){ z.doSomething() })
而且因为Javascript中的函数捕获了它们被定义的范围,所以这个代码可以被进一步简化
var Promise = require( 'bluebird' ) var emitter = someEmitter() function waitForEvent( type ){ return new Promise( function( resolve ){ //emitter has been captured from line #2 emitter.on( type, resolve ) }) } waitForEvent( 'connect' ).then( function(){ x.doSomething() }).then( function(){ y.doSomethingElse() // will trigger `eventB` eventually }) // this promise stream will begin once `eventB` has been triggered waitForEvent( 'eventB' ).then( function(){ z.doSomething() })
我面临着同样的问题,写了一个小小的承诺包装库( 控制承诺 ),允许事件发射器Promise。 你的例子的解决scheme是:
const Promise = require('bluebird'); const ControlledPromise = require('controlled-promise'); const emitter = someEmitter(); const waiting = new ControlledPromise(); function waitForEvent(type) { return waiting.call(() => { emitter.once(type, event => waiting.resolve(event)); }); } waitForEvent('connect') .then(() => x.doSomething()) .then(() => waitForEvent('eventB')) .then(() => z.doSomethingElse());
这种方法的好处:
- 自动返还已有承诺,等待处理
- 轻松访问
resolve()
/reject()
callback