add whenSynced and isSynced property with refined logic

This commit is contained in:
Kevin Jahns 2023-01-31 12:56:07 +01:00
parent 7f6c12a541
commit 7445a9ce5f
2 changed files with 86 additions and 1 deletions

View File

@ -72,13 +72,57 @@ export class Doc extends Observable {
this.shouldLoad = shouldLoad
this.autoLoad = autoLoad
this.meta = meta
/**
* This is set to true when the persistence provider loaded the document from the database or when the `sync` event fires.
* Note that not all providers implement this feature. Provider authors are encouraged to fire the `load` event when the doc content is loaded from the database.
*
* @type {boolean}
*/
this.isLoaded = false
/**
* This is set to true when the connection provider has successfully synced with a backend.
* Note that when using peer-to-peer providers this event may not provide very useful.
* Also note that not all providers implement this feature. Provider authors are encouraged to fire
* the `sync` event when the doc has been synced (with `true` as a parameter) or if connection is
* lost (with false as a parameter).
*/
this.isSynced = false
/**
* Promise that resolves once the document has been loaded from a presistence provider.
*/
this.whenLoaded = promise.create(resolve => {
this.on('load', () => {
this.isLoaded = true
resolve(this)
})
})
const provideSyncedPromise = () => promise.create(resolve => {
/**
* @param {boolean} isSynced
*/
const eventHandler = (isSynced) => {
if (isSynced === undefined || isSynced === true) {
this.off('sync', eventHandler)
resolve()
}
}
this.on('sync', eventHandler)
})
this.on('sync', isSynced => {
if (isSynced === false && this.isSynced) {
this.whenSynced = provideSyncedPromise()
}
this.isSynced = isSynced === undefined || isSynced === true
if (!this.isLoaded) {
this.emit('load', [])
}
})
/**
* Promise that resolves once the document has been synced with a backend.
* This promise is recreated when the connection is lost.
* Note the documentation about the `isSynced` property.
*/
this.whenSynced = provideSyncedPromise()
}
/**

View File

@ -257,7 +257,7 @@ export const testSubdocsUndo = _tc => {
/**
* @param {t.TestCase} _tc
*/
export const testLoadDocs = async _tc => {
export const testLoadDocsEvent = async _tc => {
const ydoc = new Y.Doc()
t.assert(ydoc.isLoaded === false)
let loadedEvent = false
@ -269,3 +269,44 @@ export const testLoadDocs = async _tc => {
t.assert(loadedEvent)
t.assert(ydoc.isLoaded)
}
/**
* @param {t.TestCase} _tc
*/
export const testSyncDocsEvent = async _tc => {
const ydoc = new Y.Doc()
t.assert(ydoc.isLoaded === false)
t.assert(ydoc.isSynced === false)
let loadedEvent = false
ydoc.once('load', () => {
loadedEvent = true
})
let syncedEvent = false
ydoc.once('sync', /** @param {any} isSynced */ (isSynced) => {
syncedEvent = true
t.assert(isSynced)
})
ydoc.emit('sync', [true, ydoc])
await ydoc.whenLoaded
const oldWhenSynced = ydoc.whenSynced
await ydoc.whenSynced
t.assert(loadedEvent)
t.assert(syncedEvent)
t.assert(ydoc.isLoaded)
t.assert(ydoc.isSynced)
let loadedEvent2 = false
ydoc.on('load', () => {
loadedEvent2 = true
})
let syncedEvent2 = false
ydoc.on('sync', (isSynced) => {
syncedEvent2 = true
t.assert(isSynced === false)
})
ydoc.emit('sync', [false, ydoc])
t.assert(!loadedEvent2)
t.assert(syncedEvent2)
t.assert(ydoc.isLoaded)
t.assert(!ydoc.isSynced)
t.assert(ydoc.whenSynced !== oldWhenSynced)
}