Install using npm:
npm install domain.io
Include in your app by passing in the io
object available in vanilla Node.js as well as Express.
var dio = require('domain.io')(io);
The root object returned by require('domain.io')(io)
consists of two methods:
Creates and returns a new domain with given name. If such a domain already exists, it returns the instance.
Deletes the domain with the given name, if it exists.
The Domain
objects returned by (1) have the following methods:
Adds the provided Socket object to this domain, and makes it addressable via id. Note that multiple sockets - for instance, connections from all devices belonging to a particular user - can be added with the same id.
Removes the provided Socket object from this domain.
Removes the socket(s) with provided id from this domain.
Emits provided event and data once to each socket in this domain.
Removes all sockets from this domain.
Emits provided event and data to the socket with given id in this domain.
Emits provided event and data once to each socket that is both in this domain as well as otherDomain.
Emits provided event and data once to each socket in this domain whose id is also contained in ids.
Emits provided event and data once to each socket that is in this domain but not in otherDomain
Emits provided event and data once to each socket that is in this domain but whose id is not in ids
Emits provided event and data once to socket(s) with unique ids across this domain and otherDomain.
Working with Socket.io in an application with several modules can painful. Domain.io maintains singleton instances of each domain, and domain(name) function returns the appropriate object if it already exists. This is less error-prone than passing around Socket.io within app.locals.
Access to the io
object is only required to create a new domain. To access Users
from a different file, you can simply do:
var Users = require('domain.io')().domain('Users');
A good analogy for how domains relate to socket connections is how ORMs relate to databases. Your ORM model and a DIO domain working together can eliminate most context-switching between business logic and database/ws logic.
Suppose User 1 adds a new photo to the 'Sports' topic. We want to send a notification to:
- All of User 1's followers
- Everyone following 'Sports'
Since there can be users falling under both 1) and 2), there is a chance they receive two notifications if we simply emit to the relevant domains.
Instead, we can use
emitToUnion
:
FollowersOf(user1Id).emitToUnion(Sports, 'photoUploadNotification', data)
On Twitter, a user gets notified if someone they follow replies to a tweet by someone else they follow. A situation like that is solvable by emitToIntersection
:
FollowersOf(user1Id)
.emitToIntersection(
FollowersOf(user2id),
'replyNotification',
data
);
Data can be sent to all Users:
topics.sports.broadcast('msg', 'Hi sports fans!');
To specific users:
var firstName = getUserFirstName(userId);
Users.emit(userId, 'greeting', 'Hello there, ' + firstName);
Or to all interested users:
var followers = Followers(userId);
followers.emit('followedUserSignIn', firstName + 'just signed in');