Events

Events are the key part of Feathers real-time functionality. All events in Feathers are provided through the NodeJS EventEmitter interface. This section describes

Important: For more information on how to send real-time events to clients, see the Channels chapter.

EventEmitters

Once registered, any service gets turned into a standard NodeJS EventEmitter and can be used accordingly.

  1. const messages = app.service('messages');
  2. // Listen to a normal service event
  3. messages.on('patched', message => console.log('message patched', message));
  4. // Only listen to an event once
  5. messsages.once('removed', message =>
  6. console.log('First time a message has been removed', message)
  7. );
  8. // A reference to a handler
  9. const onCreatedListener = message => console.log('New message created', message);
  10. // Listen `created` with a handler reference
  11. messages.on('created', onCreatedListener);
  12. // Unbind the `created` event listener
  13. messages.removeListener('created', onCreatedListener);
  14. // Send a custom event
  15. messages.emit('customEvent', {
  16. type: 'customEvent',
  17. data: 'can be anything'
  18. });

Service Events

Any service automaticaly emits created, updated, patched and removed events when the respective service method returns successfully. This works on the client as well as on the server. When the client is using Socket.io or Primus, events will be pushed automatically from the server to all connected clients. This is essentially how Feathers does real-time.

ProTip: Events are not fired until all of your hooks have executed.

Important: For information on how those events are published for real-time updates to connected clients, see the channel chapter.

Additionally to the event data, all events also get the hook context from their method call passed as the second parameter.

created

The created event will fire with the result data when a service create returns successfully.

  1. const feathers = require('@feathersjs/feathers');
  2. const app = feathers();
  3. app.use('/messages', {
  4. create(data, params) {
  5. return Promise.resolve(data);
  6. }
  7. });
  8. // Retrieve the wrapped service object which will be an event emitter
  9. const messages = app.service('messages');
  10. messages.on('created', (message, context) => console.log('created', message));
  11. messages.create({
  12. text: 'We have to do something!'
  13. });

updated, patched

The updated and patched events will fire with the callback data when a service update or patch method calls back successfully.

  1. const feathers = require('@feathersjs/feathers');
  2. const app = feathers();
  3. app.use('/my/messages/', {
  4. update(id, data) {
  5. return Promise.resolve(data);
  6. },
  7. patch(id, data) {
  8. return Promise.resolve(data);
  9. }
  10. });
  11. const messages = app.service('my/messages');
  12. messages.on('updated', (message, context) => console.log('updated', message));
  13. messages.on('patched', message => console.log('patched', message));
  14. messages.update(0, {
  15. text: 'updated message'
  16. });
  17. messages.patch(0, {
  18. text: 'patched message'
  19. });

removed

The removed event will fire with the callback data when a service remove calls back successfully.

  1. const feathers = require('@feathersjs/feathers');
  2. const app = feathers();
  3. app.use('/messages', {
  4. remove(id, params) {
  5. return Promise.resolve({ id });
  6. }
  7. });
  8. const messages = app.service('messages');
  9. messages.on('removed', (message, context) => console.log('removed', message));
  10. messages.remove(1);

Custom events

By default, real-time clients will only receive the standard events. However, it is possible to define a list of custom events on a service as service.events that should also be passed when service.emit('customevent', data) is called on the server. The context for custom events won’t be a full hook context but just an object containing { app, service, path, result }.

Important: The database adapters also take a list of custom events as an initialization option.

Important: Custom events can only be sent from the server to the client, not the other way (client to server). Learn more

For example, a payment service that sends status events to the client while processing a payment could look like this:

  1. class PaymentService {
  2. constructor() {
  3. this.events = ['status'];
  4. },
  5. create(data, params) {
  6. createStripeCustomer(params.user).then(customer => {
  7. this.emit('status', { status: 'created' });
  8. return createPayment(data).then(result => {
  9. this.emit('status', { status: 'completed' });
  10. });
  11. });
  12. }
  13. }

Using service.emit custom events can also be sent in a hook:

  1. app.service('payments').hooks({
  2. after: {
  3. create(context) {
  4. context.service.emit('status', { status: 'completed' });
  5. }
  6. }
  7. });

Custom events can be published through channels just like standard events and listened to it in a Feathers client or directly on the socket connection:

  1. client.service('payments').on('status', data => {});
  2. socket.on('payments status', data => {});