事件触发时触发提示

Jay*_*nki 17 node.js promise bluebird

我的整个项目使用(Bluebird)Promises,但是有一个使用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();
});
Run Code Online (Sandbox Code Playgroud)

在Promises链的中间读到了EventEmitter的答案.这为我提供了一种执行'connect'事件回调的方法.这是我到目前为止的地方

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
    });
});
Run Code Online (Sandbox Code Playgroud)

现在如何为'eventB'进一步链接?

Jos*_*lik 23

我假设你想为每个事件做一系列不同的事情.即使eventB是由动作触发connect,您也可以将其视为另一种逻辑流.

附注:为了避免让您和其他任何必须阅读此代码库的人感到困惑,我建议不要使用其他方法补充承诺,除非您非常详细地记录它们.

从您的示例来看,似乎以下情况可行.

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(){
    return x.doSomething()
}).then( function(){
    return y.doSomethingElse() // will trigger `eventB` eventually
})

// this promise stream will begin once `eventB` has been triggered
eventBHappened.then( function(){ 
    return z.doSomething()
})
Run Code Online (Sandbox Code Playgroud)

如果你想简化这个常数

var p = new Promise( function( resolve ){
    emitter.on( 'something', resolve )
})
Run Code Online (Sandbox Code Playgroud)

你可以使用这样的东西

function waitForEvent( emitter, eventType ){
    return new Promise( function( resolve ){
        emitter.on( eventType, resolve )
    })
}
Run Code Online (Sandbox Code Playgroud)

这将上面的代码解决方案变成了

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(){
    return x.doSomething()
}).then( function(){
    return y.doSomethingElse() // will trigger `eventB` eventually
})

// this promise stream will begin once `eventB` has been triggered
waitForEvent( emitter, 'eventB' ).then( function(){ 
    return z.doSomething()
})
Run Code Online (Sandbox Code Playgroud)

并且因为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(){
    return x.doSomething()
}).then( function(){
    return y.doSomethingElse() // will trigger `eventB` eventually
})

// this promise stream will begin once `eventB` has been triggered
waitForEvent( 'eventB' ).then( function(){ 
    return z.doSomething()
})
Run Code Online (Sandbox Code Playgroud)

  • 不能承诺只能解决一次吗?我不认为这适用于多事件API. (2认同)
  • 使用`.once`而不是`.on`,这样如果一个事件被多次触发,它不会违背你的承诺(当然,请小心使用) (2认同)