Controle de fluxo com execução assíncrona

Controle de fluxo com execução assíncrona

A teoria e os desafios por trás do controle de fluxo: Callbacks, Promises e Promises com Generators analisados de forma prática e crítica. De um lado a mais importante linguagem da Internet e seu ecossistema e do outro os principais desafios do desenvolvimento assíncrono.

C5df370a883b65279af5a7ca94a5eed7?s=128

Jean Carlo Emer

May 17, 2014
Tweet

Transcript

  1. 7.

    var  size          =  20;   var

     canvas      =  createCanvas(container);   ! for  (var  edge  =  0;  edge  <  edges;  edge++)  {          var  angle  =  Math.PI  *  edge  /  (edges  /  2);          var  range  =  createRange(centerRadius);          range.addCanvas(canvas,  edge);          range.init();   }   ! canvas.init();   Range.events();
  2. 9.

    if  (condition);   ! switch  (expression)  {}   ! for

     ([before];  [condition];  [afterEach]);   ! while  (condition);   ! for  (variable  in  object);   ! try  {}  catch  (e)  {} ... e funções
  3. 12.
  4. 16.

    Contador externo que permite condicionar a execução de código para

    o futuro. TIMERS setTimeout(callback,  3000);
  5. 17.

    Executa o download de um arquivo e ser informado do

    seu conteúdo no futuro. XML HTTP REQUEST var  req  =  new  XMLHttpRequest();   req.open('GET',  url);   req.onload  =  callback;
  6. 18.

    Monitora eventos e executa código com base em uma interação

    do usuário ou mudança de estado. DOM EVENTS el.addEventListener('click',                                              callback);
  7. 19.

    Monitora a árvore do DOM e executa código com base

    em suas mudanças. MUTATION OBSERVER new  MutationObserver(callback);
  8. 20.

    Estabelecem uma conexão permanente com o servidor para envio e

    recebimento de dados. WEB SOCKETS var  ws  =  new  WebSocket('ws://addr');   ws.onmessage  =  callback;
  9. 21.

    Estabelecem uma conexão permanente com o servidor para recebimento de

    dados. SERVER SENT EVENTS var  source  =  new  EventSource('addr');   source.onmessage  =  callback;
  10. 22.

    Executam uma porção de código em uma thread separada da

    principal. WEBWORKERS var  worker  =  new  Worker('addr.js');   worker.onmessage  =  callback;
  11. 23.

    Envio de mensagens entre diferentes documentos. WEB MESSAGES window.addEventListener('message',  

                                                   callback);
  12. 28.

    As APIs emitem um evento para indicar que o código

    da callback deve ser executado.
  13. 31.

    Tudo é executado em paralelo, exceto o seu código. -

    MIKITO TAKADA http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop
  14. 35.
  15. 37.

    SETTIMEOUT Define um timer nulo que tão logo agenda uma

    tarefa na fila de eventos. ASSÍNCRONO COM * setTimeout(callback,  0);
  16. 39.

    If nesting level is greater than 5, [...], then increase

    timeout to 4. - WHATWG TIMER SPEC http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#timers
  17. 41.

    SETIMMEDIATE Determina que uma tarefa seja colocada no fim da

    fila do laço. ASSÍNCRONO COM adeus aos timers setImmediate(callback); https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/setImmediate/Overview.html
  18. 42.

    Suportada apenas no IE10* e node.js mas com alguns polyfills:

    • postMessage e MessageChannel • <script> onreadystatechange • MutationObserver [*] IE10 bug - https://github.com/cujojs/when/issues/197 SETIMMEDIATE ASSÍNCRONO COM adeus aos timers
  19. 43.

    WEBWORKERS Código executando num ambiente separado: worker. Resultados são passados

    para o navegador através de callbacks. multithreads ASSÍNCRONO COM
  20. 44.

    WEBWORKERS Para garantir ausência de concorrência, os workers não tem

    acesso a página ou variáveis globais. Possuem acesso a XHR request, timers e a importação de scripts. multithreads ASSÍNCRONO COM
  21. 45.
  22. 48.
  23. 52.

    try  {      document.addEventListener('click',  ()  =>  {    

         //  ...          throw  new  Error('o/');      });   }  catch  (error)  {      handleError(error);   } X Tratamento de erros
  24. 53.

    document.addEventListener('click',  ()  =>  {      //  ...    

     handleError('o/');   }); aproveite as closures
  25. 54.

    $.get('products',  (products)  =>  {      products.forEach((product)  =>  {  

           var  element  =  $('<a>').text(product.name);          element.on('click',  (event)  =>  {         var  url  =  'products/'  +  product.id;              $.get(url,  (product)  =>  {                  //  ...              });          });            //  ...      });   }); X Callback hell
  26. 55.

    class  ProductsFactory  {      fetch()  {      

       $.get('products',  this.onSync.bind(this));      }      onSync(data)  {          products.forEach((item)  =>  {              var  product  =  new  Product(item).render();              //  ...          });      }   } http://javascriptissexy.com/understand-javascript-callback-functions-and-use-them
  27. 56.

    class  Product  {      constructor(data)  {      

       this.data  =  data;          this.element  =  $('<a>');      }      render()  {          this.element.text(data.name);          return  this;      }      //  ...   } organize! http://javascriptissexy.com/understand-javascript-callback-functions-and-use-them
  28. 62.

    var products; ! $.get('products', function (data) { products = data;

    }); não há nada que uma global não resolva X
  29. 64.

    $.get('gifts',  function  (data)  {      if  ($.active  ===  0)

     {            this_is_my_callback();      }   });   ! ! $.get('products',  function  (data)  {      if  ($.active  ===  0)  {            this_is_my_callback();      }   }); número de 
 requisições abertas X
  30. 68.

    var  products  =  get('products');   ! products.then(function  onFulfilled()  {  

       //  succeeded   },  function  onRejected()  {      //  error   }); retorna uma promise
  31. 69.

    var  products  =  get('products');   ! products.then(function  onFulfilled()  {  

       //  succeeded   },  function  onRejected()  {      //  error   }); quando ou se já 
 tiver um valor...
  32. 73.

    setTimeout(function  ()  {     products.then(function  ()  {    

       //  ...     });   },  9999); não tem como perder o bonde!
  33. 75.

    var  products  =  get('products');   ! var  basket  =  new

     Basket(products);   var  list      =  new  ProductsList(products); argumento
  34. 76.
  35. 78.

    new  Promise(function  (resolve,  reject)  {        if  (Math.random()

     >  .5)  {              resolve('success');        }  else  {              reject('fail');        }   }
  36. 79.

    new  Promise(function  (resolve,  reject)  {        if  (Math.random()

     >  .5)  {              resolve('success');        }  else  {              reject('fail');        }   } sucesso
  37. 80.

    new  Promise(function  (resolve,  reject)  {        if  (Math.random()

     >  .5)  {              resolve('success');        }  else  {              reject('fail');        }   } falha
  38. 81.

    function  get(url)  {      return  new  Promise(function  (resolve,  reject)

     {          var  req  =  new  XMLHttpRequest();          req.open('GET',  url);   !        req.onload  =  function  ()  {              if  (req.status  ==  200)  {                  resolve(req.response);              }  else  {                  reject(Error(req.statusText));              }          };                    req.send();      });   } http://www.html5rocks.com/en/tutorials/es6/promises
  39. 82.

    function  get(url)  {      return  new  Promise(function  (resolve,  reject)

     {          var  req  =  new  XMLHttpRequest();          req.open('GET',  url);   !        req.onload  =  function  ()  {              if  (req.status  ==  200)  {                  resolve(req.response);              }  else  {                  reject(Error(req.statusText));              }          };                    req.send();      });   } http://www.html5rocks.com/en/tutorials/es6/promises operação assíncrona
  40. 83.

    function  get(url)  {      return  new  Promise(function  (resolve,  reject)

     {          var  req  =  new  XMLHttpRequest();          req.open('GET',  url);   !        req.onload  =  function  ()  {              if  (req.status  ==  200)  {                  resolve(req.response);              }  else  {                  reject(Error(req.statusText));              }          };                    req.send();      });   } http://www.html5rocks.com/en/tutorials/es6/promises sucesso
  41. 84.

    function  get(url)  {      return  new  Promise(function  (resolve,  reject)

     {          var  req  =  new  XMLHttpRequest();          req.open('GET',  url);   !        req.onload  =  function  ()  {              if  (req.status  ==  200)  {                  resolve(req.response);              }  else  {                  reject(Error(req.statusText));              }          };                    req.send();      });   } http://www.html5rocks.com/en/tutorials/es6/promises falha
  42. 87.

    $.get('test.php').then(      function()  {          alert('$.get

     succeeded');      },  function()  {          alert('$.get  failed!');      }   ); jQuery entende* promises * aguarde, falaremos mais a respeito
  43. 90.
  44. 94.

    parser.start()      .then(function  ()  {        return

     getFiles();     })     .then(function  ()  {       //  ...     });
  45. 95.

    parser.start()      .then(function  ()  {        return

     getFiles();     })     .then(function  ()  {       //  ...     }); espera por getFiles
  46. 97.

    Promise.resolve('Yep')      .then(function(data)  {          throw

     new  Error(data);      },  function  (error)  {          //  nothing  wrong  with  Yep      })      .then(null,  function  (error)  {          console.error(error);      })      .then(function  ()  {          console.log('I  am  fine');      }); cria uma promise 
 resolvida
  47. 98.

    Promise.resolve('Yep')      .then(function(data)  {          throw

     new  Error(data);      },  function  (error)  {          //  nothing  wrong      })      .then(null,  function  (error)  {          console.error(error);      })      .then(function  ()  {          console.log('I  am  fine');      }); 1º BLOCO
  48. 99.

    Promise.resolve('Yep')      .then(function(data)  {          throw

     new  Error(data);      },  function  (error)  {          //  nothing  wrong      })      .then(null,  function  (error)  {          console.error(error);      })      .then(function  ()  {          console.log('I  am  fine');      }); ... resolvida
  49. 100.

    Promise.resolve('Yep')      .then(function(data)  {          throw

     new  Error(data);      },  function  (error)  {          //  nothing  wrong      })      .then(null,  function  (error)  {          console.error(error);      })      .then(function  ()  {          console.log('I  am  fine');      }); rejeita a 
 promise
  50. 101.

    Promise.resolve('Yep')      .then(function(data)  {          throw

     new  Error(data);      },  function  (error)  {          //  nothing  wrong  with  Yep      })      .then(null,  function  (error)  {          console.error(error);      })      .then(function  ()  {          console.log('I  am  fine');      }); 2º BLOCO
  51. 102.

    Promise.resolve('Yep')      .then(function(data)  {          throw

     new  Error(data);      },  function  (error)  {          //  nothing  wrong  with  Yep      })      .then(null,  function  (error)  {          console.error(error);      })      .then(function  ()  {          console.log('I  am  fine');      }); resolvida?
  52. 103.

    Promise.resolve('Yep')      .then(function(data)  {          throw

     new  Error(data);      },  function  (error)  {          //  nothing  wrong  with  Yep      })      .then(null,  function  (error)  {          console.error(error);      })      .then(function  ()  {          console.log('I  am  fine');      }); "tratamento"
  53. 104.

    Promise.resolve('Yep')      .then(function(data)  {          throw

     new  Error(data);      },  function  (error)  {          //  nothing  wrong  with  Yep      })      .then(null,  function  (error)  {          console.error(error);      })      .then(function  ()  {          console.log('I  am  fine');      }); sucesso!! nenhum 
 erro emitido
  54. 105.

    Promise.resolve('Yep')      .then(function(data)  {          throw

     new  Error(data);      },  function  (error)  {          //  nothing  wrong  with  Yep      })      .then(null,  function  (error)  {          console.error(error);      })      .then(function  ()  {          console.log('I  am  fine');      }); 3º BLOCO
  55. 106.

    Promise.resolve('Yep')      .then(function(data)  {          throw

     new  Error(data);      },  function  (error)  {          //  nothing  wrong  with  Yep      })      .then(null,  function  (error)  {          console.error(error);      })      .then(function  ()  {          console.log('I  am  fine');      }); resolvida?
  56. 107.

    Promise.resolve('Yep')      .then(function(data)  {          throw

     new  Error(data);      },  function  (error)  {          //  nothing  wrong  with  Yep      })      .then(null,  function  (error)  {          console.error(error);      })      .then(function  ()  {          console.log('I  am  fine');      }); termina aqui
  57. 108.
  58. 110.

    $.get('gifts',  function  (data)  {      if  ($.active  ===  0)

     {            this_is_my_callback();      }   });   ! ! $.get('products',  function  (data)  {      if  ($.active  ===  0)  {            this_is_my_callback();      }   }); X
  59. 111.

    Promise.all([      get('gifts'),        get('products')   ])

         .then(function  (results)  {          //  results[0]  -­‐>  gifts          //  results[1]  -­‐>  products      },  function  (result)  {          //  first  rejected      }); array de promises
  60. 112.

    Promise.all([      get('gifts'),        get('products')   ])

         .then(function  (results)  {          //  results[0]  -­‐>  gifts          //  results[1]  -­‐>  products      },  function  (result)  {          //  first  rejected      }); todas resolvidas ou primeira 
 rejeitada
  61. 113.

    Promise.race([      get('gifts'),        get('products')   ])

         .then(function  (results)  {          //  first  resolved      },  function  (result)  {          //  first  rejected      }); uma corrida?!
  62. 114.

    Promise.race([      get('gifts'),        get('products')   ])

         .then(function  (results)  {          //  first  resolved      },  function  (result)  {          //  or  first  rejected      }); primeiro 
 que terminar
  63. 115.

    Nosso exemplos foram todos seguindo a especificação de Promises/A+. Algumas

    implementações: • when, Q, RSVP, ... • ES6 Promises COMO USAR https://github.com/jakearchibald/es6-promise
  64. 116.

    • Excessões nas callbacks quebram a execução de código •

    Não permite chaining (1.8-) com then e sim com pipe. A IMPLEMENTAÇÃO e suas inconsistências DA JQUERY Promise.resolve(
    $.get('products'));
  65. 117.
  66. 120.

    function*  infinite()  {      var  i  =  0;  

       while  (true)  {          yield  i++;      }   }   ! var  iterator  =  infinite();   iterator.next().value;   iterator.next().value; indicativo de generator
  67. 121.

    function*  infinite()  {      var  i  =  0;  

       while  (true)  {          yield  i++;      }   }   ! var  iterator  =  infinite();   iterator.next().value;   iterator.next().value; apenas inicia
  68. 122.

    function*  infinite()  {      var  i  =  0;  

       while  (true)  {          yield  i++;      }   }   ! var  iterator  =  infinite();   iterator.next().value;   iterator.next().value; pega o i++ 
 do yield
  69. 123.

    function*  infinite()  {      var  i  =  0;  

       while  (true)  {          yield  i++;      }   }   ! var  iterator  =  infinite();   iterator.next().value;   iterator.next().value; executa o laço
 outra vez
  70. 128.

    https://github.com/visionmedia/co co(function  *(){      var  products  =  yield  get('products');

         var  gifts        =  yield  get('gifts');      console.log(products[0]);      console.log(gifts[0]);   })();
  71. 129.

    co(function  *(){      var  products  =  yield  get('products');  

       var  gifts        =  yield  get('gifts');      console.log(products[0]);      console.log(gifts[0]);   })(); https://github.com/visionmedia/co ao resolver a 
 primeira...
  72. 130.

    argumentos passados para o then https://github.com/visionmedia/co co(function  *(){    

     var  products  =  yield  get('products');      var  gifts        =  yield  get('gifts');      console.log(products[0]);      console.log(gifts[0]);   })();
  73. 131.

    https://github.com/visionmedia/co co(function  *(){      var  getProducts  =  get('products');  

       var  getGifts        =  get('gifts');   !    var  products        =  yield  getProducts;      var  gifts              =  yield  getGifts;            console.log(products[0]);      console.log(gifts[0]);   })(); paralelismo!
  74. 132.
  75. 133.

    [Promises] give you an abstraction that lets you model problems

    at a higher level. - JAMES COGLAN https://blog.jcoglan.com/2013/03/30/callbacks-are-imperative-
 promises-are-functional-nodes-biggest-missed-opportunity
  76. 134.

    Promises mean having enough memory to keep data around. -

    DREW CRAWFORD http://sealedabstract.com/code/broken-promises Haters gonna hate. - 1º COMENTÁRIO