2015-04-29 13 views
9

L'intero progetto utilizza Promises (Bluebird), ma esiste una libreria specifica che utilizza EventEmitter.Trigger Promessa quando un evento viene attivato

voglio ottenere qualcosa di simile:

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(); 
}); 

ho letto la risposta a EventEmitter in the middle of a chain of Promises. Questo mi dà un modo per eseguire il callback per l'evento 'connect'. Ecco dove ho avuto finora

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 
    }); 
}); 

Ora come catena ulteriormente per 'eventB'?

+0

Forse questo aiuterà: http://bahmutov.calepin.co/promisify-event-emitter.html –

+0

versione cache: https://web.archive.org/web/201603201007 56/http: //bahmutov.calepin.co/promisify-event-emitter.html – user1278519

risposta

12

Presumo che tu voglia fare una catena di cose diversa per ogni evento. Anche se eventB viene attivato dalle azioni di connect, puoi trattarlo come un altro flusso di logica.

Nota a margine: Per evitare confusione per voi e per chiunque altro che deve leggere questo codebase, vi consiglio contro integrando le promesse con metodi aggiuntivi se non si è molto approfondita su di loro documentazione.

Dal tuo esempio, sembra che quanto segue funzionerebbe.

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() 
}) 

Se vuoi per semplificare questa costante

var p = new Promise(function(resolve){ 
    emitter.on('something', resolve) 
}) 

si può usare qualcosa di simile

function waitForEvent(emitter, eventType){ 
    return new Promise(function(resolve){ 
     emitter.on(eventType, resolve) 
    }) 
} 

che trasforma la soluzione codice sopra in

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() 
}) 

E perché funzioni in Ja vascript catturare l'ambito in cui sono stati definiti, questo codice potrebbe essere ulteriormente semplificata in

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() 
}) 
+1

JoshWillik, grazie per il tuo aiuto :) – Jaydeep

+0

Le promesse non possono essere risolte una sola volta? Non penso che funzioni per le API multi-evento. – Grimtech

+0

@Grimtech hai ragione. Se hai bisogno di ascoltare un evento più volte, non sono lo strumento giusto – JoshWillik

1

ho affrontato con lo stesso problema e ho scritto una piccola biblioteca promessa-wrapping (controlled-promise) che permette di promisify emettitori di eventi. La soluzione per il vostro esempio è:

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()); 

I vantaggi di tale approccio:

  • ritorno automatico della promessa esistente mentre si è in attesa
  • un facile accesso alle resolve()/reject() callback
Problemi correlati