Successfully reported this slideshow.
Your SlideShare is downloading. ×

GlueCon 2016 - Threading in JavaScript

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 25 Ad

GlueCon 2016 - Threading in JavaScript

Download to read offline

A discussion of threading models in JavaScript, including Promises, AJAX queries, and the ways that JavaScript works to prevent race conditions.

A discussion of threading models in JavaScript, including Promises, AJAX queries, and the ways that JavaScript works to prevent race conditions.

Advertisement
Advertisement

More Related Content

Slideshows for you (20)

Viewers also liked (18)

Advertisement

Similar to GlueCon 2016 - Threading in JavaScript (20)

Recently uploaded (20)

Advertisement

GlueCon 2016 - Threading in JavaScript

  1. 1. Threading in Javascript or How I Came to Love Multi-Threading in JavaScript Clients Jonathan Baker Director, Developer Relations SAP Labs, LLC
  2. 2. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 2 What’s up for today? JavaScript by spec Handling long operations Ÿ Timeouts (or yield) Ÿ Workers Ÿ Promises The shared data conundrum Ÿ Loading data in separate AJAX calls Ÿ The problems with partial data - lookups? Final thoughts
  3. 3. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 3 JavaScript by spec 8.3 Execution Contexts An execution context is a specification device that is used to track the runtime evaluation of code by an ECMAScript implementation. At any point in time, there is at most one execution context that is actually executing code. This is known as the running execution context. The execution context stack is used to track execution contexts. The running execution context is always the top element of this stack. A new execution context is created whenever control is transferred from the executable code associated with the currently running execution contextto executable code that is not associated with that execution context. The newly created execution context is pushed onto the stack and becomes the running execution context. Evaluation of code by the running execution context may be suspended at various points defined within this specification. ECMA Script Specification 2017 – Draft ECMA 262 https://tc39.github.io/ecma262/#sec-execution-contexts
  4. 4. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 4 And now for a 90 second op-ed…
  5. 5. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 5 Looooonnnnngg operations My pet peeve – the unintended long operation You wrote something that shouldn’t be long, but now is – and it’s interrupting the user Proper design from the beginning – these should be in your toolbox Ÿ setTimeout() and setInterval() Ÿ Workers() Ÿ Promises()
  6. 6. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 6 Cost analysis Finding a specific user: Average Time = n/2, worst case is n. 10,000 users cached 100 rows of bets Average time: 10,000 * 100 / 2 = 500,000 checks
  7. 7. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 7 setTimeout() and setInterval() timerId = setTimeout( function(), time_in_ms ); Called a single time, with a delay of “time_in_ms” before being put on the event queue. timerId = setInterval( function(), time_in_ms ); Called multiple times. An event will be added to the queue every ”time_in_ms” Quick Recap Ÿ Full access to the global scope and DOM Ÿ Runs in the same thread as the GUI (interrupts only) Ÿ setTimeout(0) is essentially a process yield()
  8. 8. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 8 Workers() Workers are the most basic of asynchronous handlers Ÿ They run in a separate thread Ÿ Independent context, communicates by messaging var w = new worker(“script path on server”); w.onmessage = function(event) { yourData = event.data }; w.onerror = function(error) { . . . }; w.postMessage(sent_data); w.terminate();
  9. 9. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 9 Promises() Promises are the next generation of asynchronous support Finalized in 2013 (and in beta for a while) New mechanism for providing asynchronous calls with response patterns
  10. 10. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 10 Promises – how do they work? When creating asynchronous code, the response mechanism matters. Main Code var promise = new Promise(function(resolve,reject){} ); promise.then( function(result){} , function(error){} ); Promise Object (inside, running asynchronously) function(resolve,reject) { . . . if( success ) { resolve(data); } else { reject( Error(xxx) ); } }
  11. 11. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 11 Chaining Promises var getData = function(url) { return new Promise(. . .); } getData(url1).then( function(data1) { return getData(data1.url2); }).then( function(data2) { // display html with data2 }).catch( function(error) { // error dialog!! }).then( function() { $(’#spinner').hide(); } var getData = function(url) { return new Promise(. . .); } try { getData(url1); getData(url2); // display html with data2 } catch (e) { // error dialog!! } $(’#spinner’).hide(); Chain Promises? Use a function call (the stack will hold the value for the promise) Promises in parallel? Promise.all(arrayOfPromises).then( . . . );
  12. 12. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 12 Moving on to data Loading Data in separate AJAX calls The problems with partial data Angular examples
  13. 13. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 13 Simple cross-referencing data model Let’s consider data loaded from a server for a simple (if quasi-legal) application: Horse BET Person GET /horses GET /bets GET /people [ id: 1, name: Nyquist, odds: 1.65 ] [ id: 1, horse: 1, person: 42, amount: 25.00, position: win ] [ id: 42, name: Zaphod ]
  14. 14. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 14 Loading linked data effectively If we want to load the cross references, we have many options In this example: Ÿ Horses is a small list – load it immediately Ÿ Person is a huge list – load dynamically as needed (caching?) Ÿ Bets – load a page at a time (depending on what the user wants to see) Horse BET Person GET /horses GET /bets/subsetX GET /people/{id}
  15. 15. 15© 2016 SAP SE or an SAP affiliate company. All rights reserved.
  16. 16. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 16 Behind the scenes Horses load Bets load Ÿ If horses are already loaded, then bind horses to horseId in bets (Angular filter), if not, wait for them. Ÿ After bets loads, we know which Users we want. Load them Users load Ÿ After users has loaded, bind to bets
  17. 17. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 17 Do we load the users all at once, or one at a time?
  18. 18. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 18 Lets load the bets $http.get(‘/bets’).then( function(resp) { $scope.betsList = resp.data.map( function(val) { return { id : Number(val.id), accountId : Number(val.accountId), horseId : Number(val.horseId), account : undefined, horse : undefined, ...}; if ($scope.horseList) { //map horses to bets } for(var i=0, I < $scope.betsList.length ; i++ ) { $http.get(’/account/’+$scope.betsList[i].accountId).then( function(resp){ // Take the response, find the bet, and attach the account }); }; });
  19. 19. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 19 Where are the problems? $http.get(‘/bets’).then( function(resp) { $scope.betsList = resp.data.map( function(val) { return { id : Number(val.id), accountId : Number(val.accountId), horseId : Number(val.horseId), account : undefined, horse : undefined, ...}; if ($scope.horseList) { //map horses to bets } for(var i=0, i < $scope.betsList.length ; i++ ) { $http.get(’/account/’+$scope.betsList[i].accountId).then( function(resp){ // Take the response, find the bet, and attach the account }); }; });
  20. 20. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 20 Cost analysis If we start to cache data, things get interesting Finding a specific user: Average Time = n/2, worst case is n. 10,000 users cached 100 rows of bets Average time: 10,000 * 100 / 2 = 500,000 checks
  21. 21. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 21 Using Promises to move the processing function getBets() { var p1 = Promise.resolve( $.get( "/data/main/bets" ) ); var p2 = p1.then( function( response ) { return convertBetsListFromServer( response ); }) p2.then(function(finalBetsData) { $scope.betsList = finalBetsData; $scope.$apply(); // Now, start up a bunch of promises to get each individual record bindAccountsToBets( finalBetsData ); }) } (We would handle error conditions, if the screen resolution would let us!)
  22. 22. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 22 Making the Promises even smarter var p1 = new Promise( // resolve bets ); var p2 = new Promise( // resolve horses ); function linkHorsesToBets( horses, bets ) { return new Promise( function(resolve,reject) { for(var i=0, i < bets.length ; i++ ) { bets.horse = $.grep(horses, function(e){ return e.id == bets[i].horseId; }); resolve( bets ); }; }); } Promise.all( [ p1, p2 ] ).then( function( values ){ var bets = values[0]; var horses = values[1]; linkHorsesToBets( horses, bets ).then( function(result){ $scope.bets = result; }); });
  23. 23. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 23 Imagine a smarter model // If we know a column has a lookup, we could preset it Model.setColumnLookup( columnOrigin, columnForData, column_lookup_function() ) // What if we want to wait for another system? // Promise.all([a,b,...]) Model.bindAfterLoad( dataA, dataB, bind_function() ) // We could even set up a caching system for some data Model.cacheDataset()
  24. 24. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 24 Bringing it all together Identify what belongs in the user thread Ÿ Data should be loaded and ready to go! Ÿ Look for long running loops and processing Understand the toolset Ÿ setTimeout() Ÿ Worker() Ÿ Promise() Use the tools to create code that is both user-responsive and hard working
  25. 25. © 2016 SAP SE or an SAP affiliate company. All rights reserved. 25 Hit PAUSE, and discuss Questions?

×