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.
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
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
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
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
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
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
- Previous Tutorial: 01 - Hello World, as always
- Next Tutorial: 03 - Communication between Browsers