[]
js-collaboration
facilitates bidirectional client-server communication while enabling server-initiated message broadcasting to all clients within a room. This documentation details the technical implementation of:
The client sends messages to the server
The server receives and responds to messages
Message broadcast
The client sends messages to the server using the connection.send() method. Message supports multiple data types, including strings, plain objects, numbers, and arrays.
// Client side
// Send a message to the server
connection.send('hello, world!');
The server can receive client messages through the message hook.
// Server side
server.on('message', ({ connection, data }) => {
console.log('Received message from client:', data);
});
The client receives messages from the server using the connection.on('message') method.
//client side
connection.on('message', (data) => {
console.log('Received message from server:', data);
});
The server sends messages to the client using the connection.send() method.
//server side
server.on('connect', ({ connection }) => {
connection.send('hello, world!');
});
The server can not only send messages to one client but also broadcast messages to all other clients in a room using the connection.broadcast() method.
When only the roomId
parameter is provided to connection.broadcast()
, the default behavior is to broadcasting messages excluding the sender.
// Client side
connection.on('message', (data) => {
console.log('Received message from server:', data);
});
// Server side
server.on('connect', ({ connection, roomId }) => {
// When a client connects, broadcast a message to all clients in the room (excluding the sender)
connection.broadcast(`${connection.id} join ${roomId}`);
});
To broadcast messages to all room participants including the sender, configure the broadcast method with includeSelf: true
.
// Client side
connection.on('message', (data) => {
console.log('Received message from server:', data);
});// Client side
connection.on('message', (data) => {
console.log('Received message from server:', data);
});
// Server side
server.on('connect', ({ connection, roomId }) => {
// When a client connects, broadcast a message to all clients in the room (including the sender)
connection.broadcast(`${connection.id} join ${roomId}`, '', true);
});
type=note
The second parameter of broadcast() is the message type (optional), which is an empty string in this case.
Message types are used to identify the purpose or category of a message, allowing the receiver to determine whether the message is relevant to itself.
For example, in a collaboration scenario, the type could be "my-document" or "my-presence" to distinguish between document update messages and user status messages.
// Send a document update
connection.send({ content: 'New paragraph' }, 'my-document');
// Send an online status
connection.send({ userId: 'user1', active: true }, 'my-presence');
// Receive and distinguish messages
connection.on('message', (data, type) => {
if (type === 'my-document') {
console.log('Document update:', data);
} else if (type === 'my-presence') {
console.log('Status update:', data);
}
});
js-collaboration
guarantees that messages are delivered in the order they were sent. For example:
connection.send('msg1');
connection.send('msg2');
connection.send('msg3');
The receiver will always receive the messages in the order: msg1, msg2, msg3.
js-collaboration
implements an At-Most-Once Delivery mechanism defined as:
If a message is sent while the connection is disconnected, the system cannot ensure that the recipient has received the message.
When reconnecting after a disconnection, previously undelivered messages will not be automatically resent.
When the connection is disconnected, the client adopts a buffering strategy to try to retain unsent messages.
Buffering Unsent Messages: When the client calls connection.send()
and the connection is unavailable (e.g., network interruption), the message is not immediately discarded but is buffered locally on the client.
Sending After Reconnection: Once the connection is restored, buffered messages are sent in their original order.
The server does not provide a message buffering mechanism. Messages sent during a client disconnection are directly lost.
No Buffering of Messages: When the server sends messages using connection.send()
or connection.broadcast()
, if the target client is disconnected, the message is not stored.
No Resending: After a client reconnects, the server does not resend messages that were missed during the disconnection.
Due to the At-Most-Once Delivery mechanism, you need to design additional reliability mechanisms based on business requirements. Below is a common strategy:
Method: The sender includes a unique identifier (e.g., message ID) in the message, and the receiver responds with an acknowledgment message.
Implementation: If no acknowledgment is received, the sender can retry.
Use Case: Critical messages (e.g., document changes).
// Client sends a message with an ID
connection.send({ id: 'msg123', type: 'update', content: 'xxx' });
// Server acknowledges
server.on('message', ({ connection, data }) => {
connection.send({ id: data.id, type: 'ack' });
});
// Client checks for acknowledgment
connection.on('message', (data) => {
if (data.type === 'ack' && data.id === 'msg123') {
console.log('Message delivered');
}
});