Edit Page

.subscribe()

Subscribe the requesting client socket to changes/deletions of one or more database records.

Something.subscribe(req, ids);

Usage

Argument Type Details
1 req The incoming socket request (req) containing the socket to subscribe.
2 ids An array of record ids (primary key values).

When a client socket is subscribed to a record, it is a member of its dynamic "record room". That means it will receive all messages broadcasted to that room by .publish().

Example

On the server, in a controller action:

// On the server:

  subscribeToLouies: function (req, res) {
    if (!req.isSocket) {
      return res.badRequest('Only a client socket can subscribe to Louies.  But you look like an HTTP request to me.');
    }

    // Let's say our client socket has a problem with people named "louie".

    // First we'll find all users named "louie" (or "louis" even-- we should be thorough)
    User.find({ or: [{name: 'louie'},{name: 'louis'}] }).exec(function(err, usersNamedLouie){
      if (err) {
        return res.serverError(err);
      }

      // Now we'll subscribe our client socket to each of these records.
      User.subscribe(req, _.pluck(usersNamedLouie, 'id'));

      // All done!  We could send down some data, but instead, we just send an empty 200 (OK) response.
      //
      // > Although we're ok telling this vengeful client socket when our users get
      // > destroyed, it seems ill-advised to send him our Louies' sensitive user data.
      // > (We don't want to help this guy to hunt them down in real life!)
      return res.ok();

    });//</ User.find() >
  }

Then, back in our client-side code:

// On the client:

// Send a request to the "subscribeToLouies" action, subscribing this client socket
// to all future events that the server publishes about Louies.
io.socket.get('/foo/bar/subscribeToLouies', function (data, jwr){
  if (jwr.error) {
    console.error('Could not subscribe to Louie-related notifications: '+jwr.error);
    return;
  }

  console.log('Successfully subscribed.');

});

From now on, as long as our requesting client socket stays connected, it will receive a notification any time our server-side code (e.g. other actions or helpers) calls User.publish() for one of the Louies we subscribed to above.

In order for our client-side code to handle these future notifications, it must listen for the relevant event with .on(). For example:

// Whenever a `user` event is received, say something.
io.socket.on('user', function(msg) {
  console.log('Got a message about a Louie: ', msg);
});

See Concepts > Realtime for more background on the difference between rooms and events in Sails/Socket.io.

Multiple rooms per record

For some applications, you may run across the need to manage two different channels related to the same record. To accomplish this, you can combine .getRoomName() and sails.sockets.join():

// On the server, in your subscribe action…

var orgId = req.param('organizationId');
if (!orgId) { return res.badRequest(); }

if (!req.isSocket) { return res.badRequest('This action is designed for use with WebSockets.'); }

var me = await User.findOne({
  id: req.session.userId
})
.populate('globalAdminOfOrganizations', {
  where: { id: orgId },
  select: ['id']
});

// Subscribe to general notifications.
Organization.subscribe(req, orgId);

// If this user is a global admin of this organization, then also subscribe them to
// an additional private room (this is used for additional notifications intended only
// for global admins):
var isGlobalAdminOfThisOrg = (globalAdminOfOrganizations.length > 0);
if (isGlobalAdminOfThisOrg) {
  var privateRoom = Organization.getRoomName(req.param('organizationId')) + 'admins-only';
  sails.sockets.join(req, privateRoom);
}

return res.ok();

Then later, to publish to one of these rooms, just compute the appropriate room name and use sails.sockets.broadcast() to blast out your notification.

Notes

  • Be sure and check req.isSocket === true before passing in req to refer to the requesting socket. The provided req must be from a socket request, not just any old HTTP request.
  • .subscribe() will only work with requests made over a socket.io connection (e.g. using io.socket.get()), not over an http connection (e.g. using jQuery.get()). See the sails.io.js socket client documentation for information on using client sockets to send WebSockets/Socket.io messages with Sails.
  • This function does not actually talk to the database! In fact, none of the resourceful pubsub methods do. Remember: these are just a simplified abstraction layer built on top of the lower-level sails.sockets methods, designed to make your app cleaner and easier to debug by using conventional names for events/rooms/namespaces etc.

Is something missing?

If you notice something we've missed or could be improved on, please follow this link and submit a pull request to the sails-docs repo. Once we merge it, the changes will be reflected on the website the next time it is deployed.

Sails logo
  • Home
  • Get started
  • Support
  • Documentation
  • Documentation

For a better experience on sailsjs.com, update your browser.

Documentation

Reference Concepts App structure | Upgrading Contribution guide | Tutorials More

Reference

  • Application
    • Advanced usage
      • Lifecycle
      • sails.LOOKS_LIKE_ASSET_RX
      • sails.getActions()
      • sails.getRouteFor()
      • sails.lift()
      • sails.load()
      • sails.lower()
      • sails.registerAction()
      • sails.registerActionMiddleware()
      • sails.reloadActions()
      • sails.renderView()
      • sails.request()
      • sails.getBaseUrl()
    • sails.config.custom
    • sails.getDatastore()
    • sails.getUrlFor()
    • sails.log()
  • Blueprint API
    • add to
    • create
    • destroy
    • find one
    • find where
    • populate where
    • remove from
    • replace
    • update
  • Command-line interface
    • sails console
    • sails debug
    • sails generate
    • sails inspect
    • sails lift
    • sails new
    • sails version
  • Configuration
    • sails.config.*
    • sails.config.blueprints
    • sails.config.bootstrap()
    • sails.config.custom
    • sails.config.datastores
    • sails.config.globals
    • sails.config.http
    • sails.config.i18n
    • sails.config.log
    • sails.config.models
    • sails.config.policies
    • sails.config.routes
    • sails.config.security
    • sails.config.session
    • sails.config.sockets
    • sails.config.views
  • Request (`req`)
    • req._startTime
    • req.accepted
    • req.acceptedCharsets
    • req.acceptedLanguages
    • req.body
    • req.cookies
    • req.fresh
    • req.headers
    • req.host
    • req.ip
    • req.ips
    • req.isSocket
    • req.method
    • req.options
    • req.originalUrl
    • req.params
    • req.path
    • req.protocol
    • req.query
    • req.secure
    • req.signedCookies
    • req.socket
    • req.subdomains
    • req.url
    • req.wantsJSON
    • req.xhr
    • req.accepts()
    • req.acceptsCharset()
    • req.acceptsLanguage()
    • req.allParams()
    • req.file()
    • req.get()
    • req.is()
    • req.param()
    • req.setLocale()
    • req.setTimeout()
  • Response (`res`)
    • res.attachment()
    • res.badRequest()
    • res.clearCookie()
    • res.cookie()
    • res.forbidden()
    • res.get()
    • res.json()
    • res.jsonp()
    • res.location()
    • res.notFound()
    • res.ok()
    • res.redirect()
    • res.send()
    • res.serverError()
    • res.set()
    • res.status()
    • res.type()
    • res.view()
    • res.negotiate()
  • Waterline (ORM)
    • Datastores
      • .driver
      • .manager
      • .leaseConnection()
      • .sendNativeQuery()
      • .transaction()
    • Models
      • .addToCollection()
      • .archive()
      • .avg()
      • .count()
      • .create()
      • .createEach()
      • .destroy()
      • .find()
      • .findOne()
      • .findOrCreate()
      • .getDatastore()
      • .removeFromCollection()
      • .replaceCollection()
      • .stream()
      • .sum()
      • .update()
      • .validate()
      • .native()
      • .query()
    • Queries
      • .catch()
      • .decrypt()
      • .exec()
      • .fetch()
      • .intercept()
      • .limit()
      • .meta()
      • .populate()
      • .skip()
      • .sort()
      • .then()
      • .tolerate()
      • .toPromise()
      • .usingConnection()
      • .where()
    • Records
      • .toJSON()
  • WebSockets
    • Resourceful PubSub
      • .getRoomName()
      • .publish()
      • .subscribe()
      • .unsubscribe()
    • sails.sockets
      • .addRoomMembersToRooms()
      • .blast()
      • .broadcast()
      • .getId()
      • .join()
      • .leave()
      • .leaveAll()
      • .removeRoomMembersFromRooms()
      • sails.sockets.id()
    • Socket client
      • io.sails
      • io.socket
      • SailsSocket
        • Methods
        • Properties
      • io.socket.delete()
      • io.socket.get()
      • io.socket.off()
      • io.socket.on()
      • io.socket.patch()
      • io.socket.post()
      • io.socket.put()
      • io.socket.request()

Built with Love

The Sails framework is maintained by a web & mobile studio in Austin, TX, with the help of our contributors. We created Sails in 2012 to assist us on Node.js projects. Naturally we open-sourced it. We hope it makes your life a little bit easier!

Sails:
  • What is Sails?
  • Treeline IDE
  • Contribute
  • Logos/artwork
About:
  • The Sails Company
  • Security
  • News
  • Legal
Help:
  • Get started
  • Documentation
  • Docs
  • Enterprise
  • Hire us

© 2012-2018 The Sails Company. 
The Sails framework is free and open-source under the MIT License.