From e6591a7c9c558746e5a1eb8693097861fa060947 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Thu, 1 Feb 2018 05:38:02 -0800 Subject: [PATCH] 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. --- lib/index.d.ts | 2 +- lib/notifier.js | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/index.d.ts b/lib/index.d.ts index 1ba4ca7b..878d8e82 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -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) => Promise): void; function removeAllListeners(): Promise; - function removeListener(regex: string, name: string, changeCallback: (changeEvent: ChangeEvent) => void): void; + function removeListener(regex: string, name: string, changeCallback: (changeEvent: ChangeEvent) => void): Promise; function setLogLevel(logLevel: 'all' | 'trace' | 'debug' | 'detail' | 'info' | 'warn' | 'error' | 'fatal' | 'off'): void; function initiateClientReset(path: string): void; function setFeatureToken(token: string): void; diff --git a/lib/notifier.js b/lib/notifier.js index c8f43f86..ea62a36c 100644 --- a/lib/notifier.js +++ b/lib/notifier.js @@ -34,10 +34,11 @@ class FunctionListener { this.event = event; this.fn = fn; this.seen = {}; + this.pending = []; } stop() { - return Promise.resolve(); + return Promise.all(this.pending); } matches(regex, event, fn) { @@ -64,7 +65,12 @@ class FunctionListener { changes.release(); 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; } - let refCount = this.callbacks.length; + let refCount = 1; changes.release = () => { if (--refCount === 0) { changes.close(); @@ -136,8 +142,10 @@ class Listener { } for (const callback of this.callbacks) { + ++refCount; callback.onchange(changes); } + changes.release(); } available(virtualPath) {