Wait for pending notifications to complete when removing a sync listener (#1648)

With async callbacks, in-process listeners need to be able to wait for anything
currently in progress to complete just like out-of-process listeners. In
addition, removeListener() needs to be declared as returning a Promise so that
typescript code can actually use it.
This commit is contained in:
Thomas Goyne 2018-02-01 05:38:02 -08:00 committed by Kenneth Geisshirt
parent e6dc5b31cc
commit e6591a7c9c
2 changed files with 12 additions and 4 deletions

2
lib/index.d.ts vendored
View File

@ -417,7 +417,7 @@ 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 addListener(serverURL: string, adminUser: Realm.Sync.User, regex: string, name: string, changeCallback: (changeEvent: ChangeEvent) => Promise<void>): void; function addListener(serverURL: string, adminUser: Realm.Sync.User, regex: string, name: string, changeCallback: (changeEvent: ChangeEvent) => Promise<void>): void;
function removeAllListeners(): Promise<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): Promise<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;
function setFeatureToken(token: string): void; function setFeatureToken(token: string): void;

View File

@ -34,10 +34,11 @@ class FunctionListener {
this.event = event; this.event = event;
this.fn = fn; this.fn = fn;
this.seen = {}; this.seen = {};
this.pending = [];
} }
stop() { stop() {
return Promise.resolve(); return Promise.all(this.pending);
} }
matches(regex, event, fn) { matches(regex, event, fn) {
@ -64,7 +65,12 @@ class FunctionListener {
changes.release(); changes.release();
return; return;
} }
Promise.resolve(this.fn(changes)).then(() => changes.release()); const promise = Promise.resolve(this.fn(changes));
this.pending.push(promise);
promise.then(() => {
changes.release();
this.pending.splice(this.pending.indexOf(promise), 1);
});
} }
}; };
@ -128,7 +134,7 @@ class Listener {
return; return;
} }
let refCount = this.callbacks.length; let refCount = 1;
changes.release = () => { changes.release = () => {
if (--refCount === 0) { if (--refCount === 0) {
changes.close(); changes.close();
@ -136,8 +142,10 @@ class Listener {
} }
for (const callback of this.callbacks) { for (const callback of this.callbacks) {
++refCount;
callback.onchange(changes); callback.onchange(changes);
} }
changes.release();
} }
available(virtualPath) { available(virtualPath) {