Support async sync change listeners (#1626)

This commit is contained in:
Thomas Goyne 2018-01-18 03:20:17 -08:00 committed by Kenneth Geisshirt
parent 03a4dd1486
commit 0c6e254494
4 changed files with 18 additions and 11 deletions

View File

@ -119,9 +119,10 @@ class Sync {
* Change information passed when receiving sync `'change'` events. * Change information passed when receiving sync `'change'` events.
* *
* A ChangeEvent object can only be used within the callback which it is * A ChangeEvent object can only be used within the callback which it is
* supplied to, and cannot be stored for use later. In particular, this means * supplied to, and cannot be stored for use later. If the callback returns a
* that async functions cannot be used within the callback prior to accessing * promise, the ChangeEvent will remain valid until that promise is resolved
* the change event. The Realms supplied by the change event do not need to be * (and no further notifications for that same Realm will be made until it is
* resolved). The Realms supplied by the change event do not need to be
* explicitly closed. * explicitly closed.
* *
* @memberof Realm.Sync * @memberof Realm.Sync

3
lib/index.d.ts vendored
View File

@ -408,7 +408,8 @@ declare namespace Realm.Sync {
} }
function addListener(serverURL: string, adminUser: Realm.Sync.User, regex: string, name: string, changeCallback: (changeEvent: ChangeEvent) => void): void; function addListener(serverURL: string, adminUser: Realm.Sync.User, regex: string, name: string, changeCallback: (changeEvent: ChangeEvent) => void): void;
function removeAllListeners(name?: string): void; function addListener(serverURL: string, adminUser: Realm.Sync.User, regex: string, name: string, changeCallback: (changeEvent: ChangeEvent) => Promise<void>): void;
function removeAllListeners(): Promise<void>;
function removeListener(regex: string, name: string, changeCallback: (changeEvent: ChangeEvent) => void): void; function removeListener(regex: string, name: string, changeCallback: (changeEvent: ChangeEvent) => void): void;
function setLogLevel(logLevel: 'all' | 'trace' | 'debug' | 'detail' | 'info' | 'warn' | 'error' | 'fatal' | 'off'): void; function setLogLevel(logLevel: 'all' | 'trace' | 'debug' | 'detail' | 'info' | 'warn' | 'error' | 'fatal' | 'off'): void;
function initiateClientReset(path: string): void; function initiateClientReset(path: string): void;

View File

@ -57,12 +57,14 @@ class FunctionListener {
onchange(changes) { onchange(changes) {
if (this.event !== 'change' || !this.regex.test(changes.path)) { if (this.event !== 'change' || !this.regex.test(changes.path)) {
changes.release();
return; return;
} }
if (changes.isEmpty) { if (changes.isEmpty) {
changes.release();
return; return;
} }
this.fn(changes); Promise.resolve(this.fn(changes)).then(() => changes.release());
} }
}; };
@ -125,12 +127,17 @@ class Listener {
if (!changes) { if (!changes) {
return; return;
} }
let refCount = this.callbacks.length;
changes.release = () => {
if (--refCount === 0) {
changes.close();
}
}
for (const callback of this.callbacks) { for (const callback of this.callbacks) {
callback.onchange(changes); callback.onchange(changes);
} }
if (!changes.refCount) {
changes.close();
}
} }
available(virtualPath) { available(virtualPath) {

View File

@ -80,9 +80,7 @@ class Worker {
if (m.change) { if (m.change) {
const changeObj = this._changeObjects[m.change]; const changeObj = this._changeObjects[m.change];
delete this._changeObjects[m.change]; delete this._changeObjects[m.change];
if (--changeObj.refCount === 0) { changeObj.release();
changeObj.close();
}
} }
this._waiting.push(child); this._waiting.push(child);
this._next(); this._next();