Async & Parallel in JavaScript

4,066
-1

Published on

Async & Parallel in JavaScript - first draft

Published in: Technology, Business
0 Comments
13 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,066
On Slideshare
0
From Embeds
0
Number of Embeds
16
Actions
Shares
0
Downloads
0
Comments
0
Likes
13
Embeds 0
No embeds

No notes for slide

Async & Parallel in JavaScript

  1. 1. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  2. 2. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  3. 3. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  4. 4. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il // plain, non-jQuery version of hooking up an event handler var clickity = document.getElementById("clickity"); clickity.addEventListener("click", function (e) { //console log, since it's like ALL real world scenarios, amirite? console.log("Alas, someone is pressing my buttons…"); }); // the obligatory jQuery version $("#clickity").on("click", function (e) { console.log("Alas, someone is pressing my buttons…"); });
  5. 5. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  6. 6. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  7. 7. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il link.onclick = function () { clickHandler1.apply(this, arguments); clickHandler2.apply(this, arguments); };
  8. 8. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il $('input[type=submit]') .on('click', function () { console.log('foo'); }) .trigger('click'); console.log('bar'); The output is: foo bar whenever a jQuery event fires, all of its handlers will be executed sequentially without interruption.
  9. 9. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il $('#tabby,#socks').on('meow', function () { console.log(this.id + 'meowed'); }); $('#tabby').trigger('meow'); //"tabby meowed" $('#socks').trigger('meow'); //"socks meowed"
  10. 10. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  11. 11. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il var start = new Date; setTimeout(function () { var end = new Date; console.log('Timeelapsed:', end - start, 'ms'); }, 500); while (new Date - start < 1000) { }; What will be the result: 1. 500 < result < 1000 2. 1000 < result < 1500 3. 1500 < result
  12. 12. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il console.log("a"); setTimeout(function () { console.log("c"); }, 500); setTimeout(function () { console.log("d"); }, 500); setTimeout(function () { console.log("e"); }, 500); console.log("b");
  13. 13. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il init function init() { $("#spinner").show(); setup(); $("#spinner").hide(); } setup hide show
  14. 14. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il function init() { $("#spinner").show(); setTimeout( function() { setup(); $("#spinner").hide(); }, 0); }
  15. 15. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  16. 16. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  17. 17. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il try { setTimeout(function () { throw new Error('Catch me if you can!'); }, 0); } catch (e) { console.error(e); }
  18. 18. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il Option I: $.get('/data', { success: successHandler, failure: failureHandler }); Option II $.get('/data', function(error, value){ if(error) { alert('error'); returen; // Don’t forget this ! } });
  19. 19. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il var worker = { updateCustomer: function (customerInfo, callback ) { ... } // other methods, properties, etc }; worker.updateCustomer( currentCustomer, function (err, data) { alert(err || data); // this != worker });
  20. 20. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il worker.updateCustomer(currentCustomer, function (err, data) { this.showAlert(err || data); }.bind(notifier)); // using underscore/lodash worker.updateCustomer(currentCustomer, _.bind(function (err, data) { this.showAlert(err || data); }, notifier)); // using jquery worker.updateCustomer(currentCustomer, $.proxy(function (err, data) { this.showAlert(err || data); }, notifier));
  21. 21. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il worker.updateCustomer(currentCustomer, function (err, data) { this.showAlert(err || data); }.bind(notifier)); // using underscore/lodash worker.updateCustomer(currentCustomer, _.bind(function (err, data) { this.showAlert(err || data); }, notifier)); // using jquery worker.updateCustomer(currentCustomer, $.proxy(function (err, data) { this.showAlert(err || data); }, notifier)); var updateForm = { submit: function () { // get the data and store it in currentCustomer worker.updateCustomer( currentCustomer, this.showAlert.bind(this) ); }, showAlert: function (err, data) { // I don't care how, just show an alert :-) } };
  22. 22. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il for (var i = 0, len = items.length; i < len; i++) { process(items[i]); } function processArray(items, process, callback) { var todo = items.concat(); //create a clone of the original setTimeout(function () { process(todo.shift()); if (todo.length > 0) { setTimeout( arguments.callee, 25 ); } else { callback(items); } }, 25); }
  23. 23. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il function saveDocument(id) { //save the document openDocument(id) writeText(id); closeDocument(id); // update the UI to // indicate success updateUI(id); } function saveDocument(id) { var tasks =[openDocument, writeText, closeDocument, updateUI]; setTimeout(function () { //execute the next task var task = tasks.shift(); task(id); //determine if there's more if( tasks.length > 0) { setTimeout(arguments.callee, 25); } }, 25); }
  24. 24. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il function multistep(steps, args, callback){ var tasks = steps.concat(); //clone the array setTimeout(function(){ //execute the next task var task = tasks.shift(); task.apply(null, args || []); //determine if there's more if (tasks.length > 0) { setTimeout(arguments.callee, 25); } else { callback(); } }, 25); }
  25. 25. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il function timedProcessArray(items, process, callback) { var todo = items.concat(); //create a clone of the original setTimeout(function () { var start = +new Date(); do { process(todo.shift()); } while (todo.length > 0 && (+new Date() - start < 50)); if ( todo.length > 0 ) { setTimeout( arguments.callee, 25 ); } else { callback(items); } }, 25 ); }
  26. 26. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  27. 27. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  28. 28. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il var allTheCustomerThings; $("#getCustomer").click(function (cust) { var id = $("#cust-id").val(); getCustomer(id, function (cust) { allTheCustomerThings = cust; getContacts(id, function (contacts) { allTheCustomerThings.contacts = contacts; getOrders(id, function (orders) { allTheCustomerThings.orders = orders; getAccountsRecv(id, function (ar) { allTheCustomerThings.ar = ar; // OK - we got all the data, NOW WHAT?! :-) }); }); }); }); });
  29. 29. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il $.get('/mydata', { success: onSuccess, failure: onFailure, always: onAlways }); var promise = $.get('/mydata'); promise.done(onSuccess); promise.fail(onFailure); promise.always(onAlways);
  30. 30. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il var obj = { hello: function (name) {alert(name); } }, defer = $.Deferred(); defer.promise(obj); defer.resolve("John"); // Use the object as a Promise obj.done(function (name) { obj.hello(name);}) .hello("Karl"); ListenToEvents (READ) << interface >> Promise ListenToEvents (READ) TriggerEvents (WRITE) << interface >> Deferred
  31. 31. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il step1(function (value1) { step2(value1, function (value2) { step3(value2, function (value3) { step4(value3, function (value4) { // Do something with value4 }); }); }); }); Q.fcall(promisedStep1) .then(promisedStep2) .then(promisedStep3) .then(promisedStep4) .then(function (value4) { // Do something with value4 }) .catch(function (error) { // Handle any error from all above steps }) .done();
  32. 32. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il // fictional viewmodel for a mobile login screen // the ugly nested callback version var loginViewModel = (function () { var login = function () { var username = $('#loginUsername').val(); var password = $('#loginPassword').val(); el.Users.login( username, password, function () { usersModel.load( function () { mobileApp.navigate( 'views/notesView.html', function () { // YAY! We made it! }, function (err) { showError(err.message); }); }, function (err) { showError(err.message); }); }, function (err) { showError(err.message); }); }; }());
  33. 33. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il // Converted to use promises var loginViewModel = ( function () { var login = function () { var username = $('#loginUsername').val(); var password = $('#loginPassword').val(); el.Users.login(username, password) .then(function () { return usersModel.load(); }) .then(function () { mobileApp.navigate('views/notesView.html');}) .then( null, // YAY! We made it! function (err) { showError(err.message); } ); }; return { login: login }; })();
  34. 34. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il var serverData = {}; var getting1 = $.get('/1') .done(function (result) { serverData['1'] = result; }); var getting2 = $.get('/2') .done(function (result) { serverData['2'] = result; }); $.when(getting1, getting2) .done(function () { //the GET information is now in server Data... });
  35. 35. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il $.when($.ajax("/get/mail/")) .done( newMessages, updateMessageList, updateUnreadIndicator ) .fail(noMessages) .always( function () { var date = new Date(); $("#lastUpdated") .html( date.toDateString() ); } );
  36. 36. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  37. 37. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il function buildpage() { return $.Deferred(function (dfd) { dfd .pipe(function() { return $('header').fadeIn(); }) .pipe(function() { return $('#main' ).fadeIn(); }) .pipe(function() { return $('footer').fadeIn(); }); }).resolve(); } $.when( buildpage() ) .done(function() { console.log('done'); } );
  38. 38. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il varnanowrimoing = $.Deferred(); varwordGoal = 5000; nanowrimoing.progress(function (wordCount) { varpercentComplete = Math.floor(wordCount / wordGoal * 100); $('#indicator').text(percentComplete + '%complete'); }); nanowrimoing.done(function () { $('#indicator').text('Goodjob!'); }); $('#document').on('keypress', function () { var wordCount = $(this).val().split(/s+/).length; if (wordCount >= wordGoal) { nanowrimoing.resolve(); }; nanowrimoing.notify(wordCount); });
  39. 39. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il var allTheCustomerThings; $("#getCustomer").click(function (cust) { var id = $("#cust-id").val(); getCustomer(id, function (cust) { allTheCustomerThings = cust; getContacts(id, function (contacts) { allTheCustomerThings.contacts = contacts; getOrders(id, function (orders) { allTheCustomerThings.orders = orders; getAccountsRecv(id, function (ar) { allTheCustomerThings.ar = ar; // OK - we got all the data, NOW WHAT?! :-) }); }); }); }); });
  40. 40. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il $("#getCustomer").click(function (cust) { var id = $("#cust-id").val(); Q.spread([ getCustomer(id), getContacts(id), getOrders(id), getAccountsRecv(id) ], function (cust, contacts, orders, ar) { cust.contacts = contacts; cust.orders = orders; cust.ar = ar; } ); });
  41. 41. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  42. 42. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  43. 43. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  44. 44. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  45. 45. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il var worker = new Worker('myThread.js'); worker.addEventListener('message',function(e){console.log(e.data);}); worker.postMessage('input message'); msg //myThread.js self.addEventListener( 'message' , doEcho ); function doEcho (e) { self.postMessage('Echo: ' + e.data) }; doEchoEcho
  46. 46. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il // Test if Dedicated Web Workers are available if (window.Worker) { g_bDedicatedWorkersEnabled = true; } // Test if Shared Web Workers are available if (window.SharedWorker) { g_bSharedWorkersEnabled = true; }
  47. 47. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  48. 48. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  49. 49. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il worker.postMessage( {data: int8View, moreData: anotherBuffer}, [int8View.buffer, anotherBuffer] );
  50. 50. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il importScripts('script1.js', 'script2.js');
  51. 51. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il  In Chrome, there's a nice page to view all of the created blob URLs: chrome://blob-internals/ var blob = new Blob([ "onmessage = function(e) { postMessage('msg from worker'); }"]); // Obtain a blob URL reference to our worker 'file'. var blobURL = window.URL.createObjectURL(blob); var worker = new Worker(blobURL); worker.onmessage = function (e) { // e.data == 'msg from worker' }; worker.postMessage('msg'); // Start the worker
  52. 52. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il function onError(e) { document.getElementById('error').textContent = [ 'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message ].join(''); } function onMsg(e) { ... } var worker = new Worker('workerWithError.js'); worker.addEventListener('message', onMsg, false); worker.addEventListener('error', onError, false);
  53. 53. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  54. 54. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  55. 55. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  56. 56. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il var calculator = operative({ add: function (a, b) { return a + b; } }); // Calc on web worker and return the result to UI thread. calculator.add(1, 2, function (result) { result; // => 3 });
  57. 57. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  58. 58. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  59. 59. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  60. 60. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  61. 61. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  62. 62. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il when.map(srcs, loadImage) .then( function gotEm(imageArray) { doFancyStuffWithImages(imageArray); return imageArray.length; }, function doh(err) { handleError(err); } ) .then( function shout(count) { // This will happen after gotEm() and count // is the value returned by gotEm() alert('see my new ' + count + ' images?'); } );
  63. 63. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  64. 64. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  65. 65. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il http://code.dougneiner.com/presentations/machina/
  66. 66. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  67. 67. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  68. 68. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il Observable Subscribe Observer
  69. 69. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il function CreateObservable(element, eventType) { return Rx.Observable.create( function (observer) { function eventHandler(eventObj) { observer.onNext(eventObj); } // keep simple for this example and ignore // addEventListener/attachEvent browser differences element.addEventListener(eventType, eventHandler); return function () { element.removeEventListener(eventType, eventHandler); }; }); };
  70. 70. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il var observable = CreateObservable( document.getElementById('button'), 'click') .skip(2) .take(2) .select(function (evt) { return "button clicked"; });
  71. 71. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il var observer = Rx.Observer.create( //onNext function(evt){ alert(evt);}, //onError function(err){ alert('error');}, //onComplete function (){ alert('done'); } ); observable.subscribe(observer);
  72. 72. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il MSFT 27.01 INTC 21.75 MSFT 27.96 MSFT 31.21 INTC 22.54 INTC 20.98 MSFT 30.73 from tick in ticks
  73. 73. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il MSFT 27.01 INTC 21.75 MSFT 27.96 MSFT 31.21 INTC 22.54 INTC 20.98 MSFT 30.73 27.01 27.96 31.21 30.73 21.75 22.54 20.98 from tick in ticks group tick by tick.Symbol
  74. 74. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il MSFT 27.01 INTC 21.75 MSFT 27.96 MSFT 31.21 INTC 22.54 INTC 20.98 MSFT 30.73 from tick in ticks group tick by tick.Symbol into company from openClose in company.Buffer(2, 1) [27.01, 27.96] [27.96, 31.21] [31.21, 30.73] [21.75, 22.54] [22.54, 20.98]
  75. 75. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il MSFT 27.01 INTC 21.75 MSFT 27.96 MSFT 31.21 INTC 22.54 INTC 20.98 MSFT 30.73 from tick in ticks group tick by tick.Symbol into company from openClose in company.Buffer(2, 1) let diff = (openClose[1] – openClose[0]) / openClose[0] 0.034 0.104 -0.015 0.036 -0.069
  76. 76. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il MSFT 27.01 INTC 21.75 MSFT 27.96 MSFT 31.21 INTC 22.54 INTC 20.98 MSFT 30.73 from tick in ticks group tick by tick.Symbol into company from openClose in company.Buffer(2, 1) let diff = (openClose[1] – openClose[0]) / openClose[0] where diff > 0.1 0.034 0.104 -0.015 0.036 -0.069
  77. 77. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il MSFT 27.01 INTC 21.75 MSFT 27.96 MSFT 31.21 INTC 22.54 INTC 20.98 MSFT 30.73 from tick in ticks group tick by tick.Symbol into company from openClose in company.Buffer(2, 1) let diff = (openClose[1] – openClose[0]) / openClose[0] where diff > 0.1 select new { Company = company.Key, Increase = diff } Company = MSFT Increase = 0.104
  78. 78. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il  Autocomplete (source) (demo)  Canvas Painting (source) (demo)  Drag and Drop (source) (demo)  AMD and Require.js Integration (source) (demo)  Time Flies Like an Arrow (source) (demo) Link to Start with: Introduction to the Rx for JavaScript
  79. 79. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il function draw() { // Drawing code goes here } setInterval(draw, 100); function draw() { setTimeout(draw, 100); // Drawing code goes here } draw();
  80. 80. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il function draw() { requestAnimationFrame(draw); // Drawing code goes here } draw(); The frame rate of your browser and computer, but typically it’s 60fps. The key difference here is that you are requesting the browser to draw your animation at the next available opportunity, not at a predetermined interval.
  81. 81. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il polyfill var fps = 15; function draw() { setTimeout(function () { requestAnimationFrame(draw); // Drawing code goes here }, 1000 / fps); } Frame rate
  82. 82. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il
  83. 83. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il Asynchronous JS: Callbacks, Listeners, Control Flow Libs and Promises Five Patterns to Help You Tame Asynchronous JavaScript The basics of Web Workers How JavaScript Timers Work http://creativejs.com/resources/requestanimationframe/
  84. 84. © 2013 E4D LTD. All rights reserved. Tel: 054-5-767-300, Email: Eyal@E4D.co.il eyalvardi.wordpress.com

×