Once registered through app.use
, a Feathers service gets turned into an EventEmitter that sends created
, updated
, patched
and removed
events when the respective service method returns successfully. On the server and with the Feathers client you can listen to them by getting the service object with app.service('<servicepath>')
and using it like a normal event emitter. Event behavior can also be customized or disabled using event filters.
ProTip: Events are not fired until all of your after hooks have executed.
There are two types of events: Standard and Custom.
Standard events are built in to every service and are enabled by default. A standard event exists for each service method that affects data:
created
updated
patched
removed
The created
event will fire with the result data when a service create
returns successfully.
const feathers = require('feathers');
const app = feathers();
app.use('/messages', {
create(data, params) {
return Promise.resolve(data);
}
});
// Retrieve the wrapped service object which will be an event emitter
const messages = app.service('messages');
messages.on('created', message => console.log('created', message));
messages.create({
text: 'We have to do something!'
});
The updated
and patched
events will fire with the callback data when a service update
or patch
method calls back successfully.
const feathers = require('feathers');
const app = feathers();
app.use('/my/messages/', {
update(id, data) {
return Promise.resolve(data);
},
patch(id, data) {
return Promise.resolve(data);
}
});
const messages = app.service('my/messages');
messages.on('updated', message => console.log('updated', message));
messages.on('patched', message => console.log('patched', message));
messages.update(0, {
text: 'updated message'
});
messages.patch(0, {
text: 'patched message'
});
The removed
event will fire with the callback data when a service remove
calls back successfully.
const feathers = require('feathers');
const app = feathers();
app.use('/messages', {
remove(id, params) {
return Promise.resolve({ id });
}
});
const messages = app.service('messages');
messages.on('removed', messages => console.log('removed', messages));
messages.remove(1);
By default, real-time clients will only receive the standard service events. However, it is possible to define a list of custom events on a service as service.events
that should also be passed. For example, a payment service that sends status events to the client while processing a payment could look like this:
class PaymentService {
constructor() {
this.events = ['status'];
},
create(data, params) {
createStripeCustomer(params.user).then(customer => {
this.emit('status', { status: 'created' });
return createPayment(data).then(result => {
this.emit('status', { status: 'completed' });
});
});
createPayment(data)
}
}
Now clients can listen to the <servicepath> status
event. Custom events can be filtered just like standard events.
It is easy to listen for these events on the client or the server. Depending on the socket library you are using it is a bit different so refer to either the Socket.io or Primus docs.
Binding to service events is great for logging or updating internal state. However, things like sending an email when creating a new user should be implemented through hooks.
The reason is that if you have multiple application instances of the same app, they will all be listening for, in this example, a user created
event. All of their event handlers would be triggered and each app would send an email. Sending multiple emails to your user when they sign up (N X # of apps) is definitely not intended and not very scalable.
Furthermore, with hooks it is much easier to give feedback to the user when an error happened.