[]
SharedDoc represents a shared document instance, used to manage document snapshots (snapshot
) and operations (op
), synchronizing data with the server through a connection (Connection
). It supports the Operational Transformation (OT) mechanism to ensure consistency of multi-user operations. This document explains how to use SharedDoc
on the client side, including:
Initialize SharedDoc
Create or delete documents
Request and update document snapshots
Submit, receive, and transform operations
Listen for events
Property Name | Description | Types |
---|---|---|
| Returns the unique identifier of the shared document. |
|
| Indicates the version number of the current snapshot. | `number |
| Indicates the operation type (Operational Transformation type) of the snapshot. | `OT_Type<S, T> |
| Indicates the data of the current snapshot. | `S |
| Returns the connection object of the shared document. |
|
Retrieve the document's snapshot data, with the result stored in doc.data
.
fetch(): Promise<void>
Return
Promise<void>
: Returns a promise that resolves after the snapshot is fetched, the fetched snapshot data is 'doc.data'.
Example
try {
await doc.fetch();
if (!doc.type) {
return console.log('Document does not exist');
}
console.log('Document snapshot', doc.data);
} catch (error) {
if (error) {
return console.error(error);
}
}
Retrieve the document's snapshot data and listen for subsequent updates.
subscribe(): Promise<void>
Return
Promise<void>
: Returns a promise that resolves after the snapshot is subscribed, the subscribed snapshot data is 'doc.data'.
Example
try {
await doc.subscribe();
if (!doc.type) {
return console.log('Document does not exist');
}
console.log('Document snapshot', doc.data);
doc.on('op', (op, source) => {
console.log('Document updated', op, source);
});
} catch (error) {
if (error) {
return console.error(error);
}
}
Submit an operation to the document.
submitOp(component: T, options?: IOptions): Promise<void>
Parameters
component
(T
): The op component.
options
(IOptions
): Options for the operation (optional).
Return
Promise<void>
: Returns a promise that resolves after the op is submitted.
Example
// Insert text 'x' at position 1
await doc.submitOp({ pos: 1, text: 'Hi' }, { source: doc.connection.id });
console.log('Operation submitted');
Create a new document.
create(data: S, type: string, options: IOptions): Promise<void>
Parameters
data
(S
): The data used to initialize the snapshot.
type
(string
): The URI of the OT type.
options
(IOptions
): Options for the operation.
Return
Promise<void>
: Returns a promise that resolves after the document is created.
Example
try {
await doc.create('Hello', textType.uri, {});
console.log('Document created successfully:', doc.data); // "Hello"
} catch (err) {
console.error('Creation failed:', err);
}
Retrieve historical snapshot data of the document.
fetchHistorySnapshot(options: IHistorySnapshotRequestOptions): Promise<ISnapshot<S>>
Parameter
options
(IHistorySnapshotRequestOptions
): Historical snapshot request options.
Return
Promise<ISnapshot<S>>
: Returns a promise that resolves after the history snapshot is fetched.
Example
const snapshot = await doc.fetchHistorySnapshot({ version: 6 }, textType.uri, {});
console.log('Document created successfully, snapshot :', snapshot);
Delete the document.
del(options: IOptions): Promise<void>
Parameter
options
(IOptions
): Deletion options.
Return
Promise<void>
: Returns a promise that resolves after the document is deleted.
Forcefully rollback the snapshot data to the latest version.
hardRollback(): Promise<void>
Return
Promise<void>
: Returns a promise that resolves when the rollback is complete.
Destroy the instance and release all resources.
destroy(): void
SharedDoc
supports the following events, managed by the on
, once
, and off
methods:
Event Name | Description | Parameters |
---|---|---|
| Triggered when an error occurs. |
|
| Triggered after retrieving or subscribing to a snapshot. | None |
| Triggered when the document is created. |
|
| Triggered before an operation is applied. |
|
| Triggered after an operation is applied. |
|
| Triggered when the document is deleted. |
|
| Triggered during a forced rollback. | None |
Register an event listener.
on<NAME extends keyof ISharedDocEvents<S, T>>(name: NAME, f: ISharedDocEvents<S, T>[NAME]): ISharedDocEvents<S, T>[NAME];
Parameters
name
(NAME
): Event name, must be a key in the ISharedDocEvents<S, T>
interface.
f
(ISharedDocEvents<S, T>[NAME]
): Event handler function.
Return
ISharedDocEvents<S, T>[NAME]
: The registered event handler.
Example
doc.on('op', (op, source) => {
if (source !== doc.connection.id) {
console.log('receive op from server:', op);
}
});
Register an event listener that triggers only once.
once<NAME extends keyof ISharedDocEvents<S, T>>(name: NAME, f: ISharedDocEvents<S, T>[NAME]): void;
Parameters
name
(NAME
): Event name.
f
(ISharedDocEvents<S, T>[NAME]
): Event handler function.
Example
doc.once('op', (op, source) => {
console.log('op', op, source);
});
Remove a specific event listener.
off<NAME extends keyof ISharedDocEvents<S, T>>(name: NAME, f: ISharedDocEvents<S, T>[NAME]): void;
Parameters
name
(NAME
): Event name.
f
(ISharedDocEvents<S, T>[NAME]
): Event handler function to remove.
The following figure shows a collaborative process.
// Initialize the UI component. xxx.uiComponent is fictional and should be replaced with an actual UI component implementation, such as Quill or others.
const uiComponent = new xxx.uiComponent();
// Subscribe to the document
doc.subscribe().then(async () => {
// Create the document if it does not exist
if (!doc.type) {
try {
await doc.create('Hello', textType.uri, {});
console.log('Created successfully:', doc.data);
} catch (error) {
console.error('Creation failed:', error);
return;
}
}
uiComponent.setText(doc.data);
// Listen for operations
doc.on('op', (op, source) => {
if (source === doc.connection.id) {
return;
}
console.log('Received operation:', op, 'Current data:', doc.data);
uiComponent.applyOp(op.pos, op.text); // Prefer incremental updates
// Or uiComponent.setText(doc.data); // Full update
});
// Listen for UI component operations and submit to the server
uiComponent.on('op', (op) => {
await doc.submitOp(op, { source: doc.connection.id });
});
})
Try to build a real-time collaborative text editor: Tutorial: Real-Time Collaborative Text Editor.