2015-04-29 3 views
9

Весь мой проект использует (Bluebird) Promises, но есть одна конкретная библиотека, которая использует EventEmitter.Trigger Promise при возникновении события

Я хочу, чтобы достичь чего-то вроде:

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

Я прочитал ответ на EventEmitter in the middle of a chain of Promises. Это дает мне возможность выполнить обратный вызов для события «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 
    }); 
}); 

Теперь, как цепь далее для «» событие В?

+0

Возможно, это поможет: http://bahmutov.calepin.co/promisify-event-emitter.html –

+0

кэшированная версия: https://web.archive.org/web/201603201007 56/http: //bahmutov.calepin.co/promisify-event-emitter.html – user1278519

ответ

12

Я предполагаю, что вы хотите сделать другую цепочку вещей для каждого события. Даже если eventB запускается действиями connect, вы можете рассматривать его как другой поток логики.

Side Примечание: Для того, чтобы избежать путаницы для вас и всех, кто должен прочитать эту кодовую, я бы не рекомендовал дополняющего обещаний с дополнительными методами, если вы не очень тщательно об их документирования.

Из вашего примера, похоже, что следующее будет работать.

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

который превращает раствор кода выше в

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

И поскольку функции в Ja vascript захватить сферу, где они были определены, этот код может быть дополнительно упрощен до

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, спасибо за вашу помощь :) – Jaydeep

+0

Не можете обещать только разрешить один раз? Я не думаю, что это будет работать для API с несколькими событиями. – Grimtech

+0

@Grimtech ты прав. Если вам нужно прослушивать событие несколько раз, это неправильный инструмент – JoshWillik

1

я столкнулся с той же проблемой, и написал маленькую библиотеку обещания обертывани (controlled-promise), что позволяет promisify излучателей событий. Раствор для примера:

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() обратных вызовов
Смежные вопросы