{"push_id":1047687442,"size":1,"distinct_size":1,"ref":"refs/heads/cancellable-promise-improvements","head":"767671072bb8fc9442a7b1deb15244af2a955fb1","before":"8cb97cb20b116c50710649d5938007ac0239584b","commits":[{"sha":"767671072bb8fc9442a7b1deb15244af2a955fb1","author":{"email":"781b0706163b25314981dcc0768997c2fe62a441@users.noreply.github.com","name":"K. Adam White"},"message":"Improve CancellablePromise to permit state access within executorFn\n\n**Description of the problem this pull request fixes**\n\nChanges proposed in this pull request:\n- Modify the CancellablePromise to permit its executor function to inspect its\n  cancellation state\n- Build a 10ms timeout into the model parse method to permit intermediate\n  cancellation without having to debounce the entire parse method\n- Throttle the vega update function as a separate store listener\n\n** If submitting code for review: **\n\n**This PR includes:**\n\n- [x] Tests\n- [x] functional comments\n\n**Steps to functionally test this:**\n\n- Smoke\n- Unit test suite\n- Functional\n\nA conceptual weakness of our CancellablePromise is that it did not give\nitself any internal means to inspect the state of the cancellation,\nprecluding conditional actions inside the promise executor function.\n\nOne common scenario for which this utility was written is the Parse cycle:\nimagine the following scenario,\n\n1. User adds a mark\n2. Mark registers its signals\n3. User alters mark's signal values\n\nThe first two of these actions require the Vega model to be re-created;\nthe third requires the first two to have taken place, or the signals will\nnot be present when Lyra tries to set those signal values. Because mark\naddition and signal registration both require a Vega re-parse, we\ninitialize the re-parse for each action; but we only care about the final\nstate, not the state after (1) alone. Exposing promise cancellation\nstatus with a bound executor function permits the promise to be created\nwith a built-in debounce of 10ms, so that if the 2nd action happens\nimmediately after the first in execution order, we don't have to begin\nto invoke the model parse at all. This is slighty more efficient than\nsimply throwing away the result of the parse.\n\nThe output of these debug statements:\n```diff\ndiff --git a/src/js/model/index.js b/src/js/model/index.js\nindex 9764276..c4b093a 100644\n--- a/src/js/model/index.js\n+++ b/src/js/model/index.js\n@@ -229,6 +229,7 @@ var parsePromise = null;\n  * parsed and rendered.\n  */\n model.parse = function(el) {\n+  console.log('parsing');\n   el = el || '#vis';\n   if (parsePromise) {\n     // A parse is already in progress; cancel that parse's callbacks\n@@ -237,15 +238,19 @@ model.parse = function(el) {\n\n   // Start the newly-requested parse within a cancellable promise\n   parsePromise = new CancellablePromise(function(resolve, reject) {\n+    console.log('- Starting promise');\n\n     // Debounce parse initiation very slightly to handle re-starts on subsequent\n     // store listener digest cycles: CancellablePromise exposes its state through\n     // this.cancel.\n     var that = this;\n     setTimeout(function() {\n+      console.log('  - Checking for permission to continue...');\n       if (that.cancelled) {\n+      console.log('    - cancelled...');\n         return;\n       }\n+      console.log('    - ok!');\n       // Recreate the vega spec\n       vg.parse.spec(model.manipulators(), function(err, chart) {\n         if (err) {\n@@ -257,6 +262,7 @@ model.parse = function(el) {\n   });\n\n   return parsePromise.then(function(chart) {\n+    console.log('      - Done!');\n     model.view = chart({\n       el: el\n     });\n@@ -373,6 +379,7 @@ function updateAllSignals(state) {\n\n function initiateReparse() {\n   model.parse().then(function() {\n+    console.log('        - done parsing');\n     store.dispatch(parseInProgress(false));\n   });\n }\n```\nis this log:\n![image](https://cloud.githubusercontent.com/assets/442115/14217614/1baa5182-f81d-11e5-88d4-f3cf89b621a7.png)\nYou can see that of the 7 vega model re-parse requests received, this\nchange causes only two vega parse actions to run, and only one parse\ncallback to fire: the first five requests are cancelled within their\n10ms debounce window, while the 6th is cancelled once the parse is in\nprogress but before the chart has completed and been injected into the\npage.\n\nThis change allows us to remove the debounce on the parse method, cleaning\nup the model code a bit. We also move to using a throttled vega update\nmethod to avoid unnecessary updates.","distinct":true,"url":"https://api.github.com/repos/vega/lyra/commits/767671072bb8fc9442a7b1deb15244af2a955fb1"}]}