LoginSignup
32
30

More than 5 years have passed since last update.

EventEmitterをPromiseに対応させる

Last updated at Posted at 2015-10-28

react-router@1.0.0-rc3を使っていると、onEnterでStoreを更新して、終わってからRouteへ移動したい。Angularで言うui-routerのresolveが欲しいと思っていました。

EventEmitterを継承して.emitをオーバーライドすれば対応可能です。軽くテストを通したライブラリも公開しています1

具体的には下記のように実装します。

async-emitter.js
// Dependencies
import {EventEmitter} from 'events'

// Public
class AsyncEmitter extends EventEmitter{
  emit(event,...args){
    let promises= []

    this.listeners(event).forEach(listener=>{
      promises.push(listener(...args))
    })

    return Promise.all(promises)
  }
}

export default AsyncEmitter

最後にPromise.allで結果を梱包するので、配列の結果か、最初のエラーを補足します。

async-emitter-test.js
import AsyncEmitter from './async-emitter'

let emitter= new AsyncEmitter

// Add event listeners
emitter.on('foo',(arg1)=>{
  return new Promise((resolve,reject)=>{
    if(arg1==null){
      resolve('bar')
    }
    else{
      reject(new Error('beep'))
    }
  })
})

// Dispatch the `foo` event
emitter.emit('foo')
.then(values=>{
  console.log(values[0] === 'bar') // true

  // expect to be rejected
  return emitter.emit('foo','kaboom')
})
.catch(reason=>{
  console.error(reason.message === 'beep') // true
})
babel-node async-emitter-test.js
true
true

react-router@1.0.0-rc3では、onEnterの第三引数にcallbackを受けますので、上手く活用出来ると思います。


  1. v0.4.0から、.emit.emitParallelにメソッド名を変更しました。 

32
30
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
30