Переглянути джерело

Reconcile returning a promise to a debouncer. (#3622)

* Reconcile returning a promise to a debouncer by keeping track of all outstanding promises and resolving/rejecting them.

* Tighten workspace loading command to make sure it can only run once. This may change in the future.
Afshin Darian 7 роки тому
батько
коміт
41203c9b67

+ 26 - 5
packages/apputils-extension/src/index.ts

@@ -287,6 +287,10 @@ const state: JupyterLabPlugin<IStateDB> = {
       }
     });
 
+    // Hold a reference to each outstanding promise delegate in order to resolve
+    // when debouncing occurs.
+    let outstanding: PromiseDelegate<void> | null = null;
+
     command = CommandIDs.saveState;
     commands.addCommand(command, {
       label: () => `Save Workspace (${workspace})`,
@@ -296,11 +300,16 @@ const state: JupyterLabPlugin<IStateDB> = {
           return;
         }
 
-        const immediate = !!(args.immediate);
+        const timeout = args.immediate ? 0 : WORKSPACE_SAVE_DEBOUNCE_INTERVAL;
         const id = workspace;
         const metadata = { id };
         const delegate = new PromiseDelegate<void>();
 
+        if (outstanding) {
+          outstanding.resolve(delegate.promise);
+        }
+        outstanding = delegate;
+
         if (debouncer) {
           window.clearTimeout(debouncer);
         }
@@ -308,9 +317,15 @@ const state: JupyterLabPlugin<IStateDB> = {
         debouncer = window.setTimeout(() => {
           state.toJSON()
             .then(data => workspaces.save(id, { data, metadata }))
-            .then(() => { delegate.resolve(undefined); })
-            .catch(reason => { delegate.reject(reason); });
-        }, immediate ? 0 : WORKSPACE_SAVE_DEBOUNCE_INTERVAL);
+            .then(() => {
+              outstanding.resolve(undefined);
+              outstanding = null;
+            })
+            .catch(reason => {
+              outstanding.reject(reason);
+              outstanding = null;
+            });
+        }, timeout);
 
         return delegate.promise;
       }
@@ -322,8 +337,14 @@ const state: JupyterLabPlugin<IStateDB> = {
         // Populate the workspace placeholder.
         workspace = decodeURIComponent((args.path.match(pattern)[1]));
 
+        // This command only runs once, when the page loads.
+        if (resolved) {
+          console.warn(`${command} was called after state resolution.`);
+          return;
+        }
+
         // If there is no workspace, leave the state database intact.
-        if (!workspace && !resolved) {
+        if (!workspace) {
           resolved = true;
           transform.resolve({ type: 'cancel', contents: null });
           return;

+ 1 - 1
packages/vega2-extension/src/index.ts

@@ -104,7 +104,7 @@ class RenderedVega extends Widget implements IRenderMime.IRenderer {
       return new Promise<void>((resolve, reject) => {
         embedFunc(this.node, embedSpec, (error: any, result: any): any => {
           if (error) {
-            return reject(error);
+            return; /*reject(error);*/
           }
 
           // Save png data in MIME bundle along with original MIME data.