Skip to content

Latest commit

 

History

History
215 lines (154 loc) · 5.92 KB

02 - Using Event Emit.md

File metadata and controls

215 lines (154 loc) · 5.92 KB

[SUGOS Tutorial] 02 - Using Event Emit

In the Previous Tutorial, we learned simple call/return function.

Now, we will try using event emitter interface. Fire events from actors and receive them on callers.

eyecatch

Try It Out

Prepare project

For the beginning, prepare project directory.

mkdir sugos-tutorial-02
cd sugos-tutorial-02
npm init -y

Then, install dependencies.

npm install sugo-actor sugo-caller sugo-hub co asleep -S

Running Hub Server

Hub server script is same as the previous tutorial.

hub.js

#!/usr/bin/env node

'use strict'

const sugoHub = require('sugo-hub')
const co = require('co')

co(function * () {
  let hub = sugoHub({})
  yield hub.listen(3000)
  console.log(`SUGO Cloud started at port: ${hub.port}`)
}).catch((err) => {
  console.error(err)
  process.exit(1)
})

Then, execute with node.

node ./hub.js

Declaring a Module to Fire Events

Define a module which fires tick each second and say "boom!"

modules/time-bomb.js

/**
 * Sample of module with event emitting
 * @module tableTennis
 */
'use strict'

const { Module } = require('sugo-actor')
const co = require('co')
const asleep = require('asleep')

const timeBomb = new Module({
  countDown (count) {
    const s = this
    return co(function * () {
      let abort = () => { count = -1 }
      s.on('abort', abort) // Listen to events from the caller
      while (count > 0) {
        count--
        s.emit('tick', { count }) // Emit an event to the caller
        yield new Promise((resolve) =>
          setTimeout(() => resolve(), 1000)
        )
      }
      s.off('abort', abort) // Remove event listener
      let isAborted = count === -1
      return isAborted ? 'hiss...' : 'booom!!!'
    })
  }
})

module.exports = timeBomb

The this inside module method inherits EventEmitter and has .on, .off and .emit()methods

Setting the Module to Actor and Connect to Hub Server

Create an actor instance

actor.js

#!/usr/bin/env node

'use strict'

const sugoActor = require('sugo-actor')
const co = require('co')
const timeBomb = require('./modules/time-bomb')

co(function * () {
  let actor = sugoActor({
    host: 'localhost:3000',
    key: 'my-actor-02',
    /** Modules to load */
    modules: {
      timeBomb
    }
  })

// Connect to hub
  yield actor.connect()

  console.log(`Actor connected to: ${actor.socket.io.uri}`)
}).catch((err) => console.error(err))
node ./actor.js

Calling from Caller

Call the timeBomb module from caller side. The module instance returns from .get() on caller side is also an instance of EventEmitter.

caller.js

#!/usr/bin/env node
'use strict'

const sugoCaller = require('sugo-caller')
const co = require('co')

co(function * () {
  let caller = sugoCaller({
    host: 'localhost:3000'
  })

  // Connect to actor
  let myActor02 = yield caller.connect('my-actor-02')
  let timeBomb = myActor02.get('timeBomb')
  let tick = (data) => console.log(`tick: ${data.count}`)
  timeBomb.on('tick', tick) // Add listener
  let booom = yield timeBomb.countDown(10)
  console.log(booom)
  timeBomb.off('tick', tick) // Remove listener
}).catch((err) => console.error(err))

Note that yield timeBomb.countDown(10) waits until the count down finished. Internally, promise state is pending until actor returns.

Now, execute the script and do count down.

node ./caller.js

Conclusion

  • this in module methods is an instance of EventEmitter
  • Fire and receive events via .on(), .off(), .emit() methods.
  • While an promise on actor side is pending, caller also waits

Code snippets of this tutorial are also available here

You may Want to Read

Links