Slide 1

Slide 1 text

CONTROLE DE FLUXO com execução assíncrona

Slide 2

Slide 2 text

http://jcemer.com

Slide 3

Slide 3 text

Um dos organizadores RSJS FRONT IN POA http://frontinpoa.com.br http://rsjs.org

Slide 4

Slide 4 text

Desenvolvedor front-end no GRUPO RBS http://gruporbs.com.br

Slide 5

Slide 5 text

uma explicação breve FLUXO

Slide 6

Slide 6 text

ORDEM DE EXECUÇÃO das INSTRUÇÕES

Slide 7

Slide 7 text

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();

Slide 8

Slide 8 text

Algumas instruções são responsáveis por guiar o fluxo.

Slide 9

Slide 9 text

if  (condition);   ! switch  (expression)  {}   ! for  ([before];  [condition];  [afterEach]);   ! while  (condition);   ! for  (variable  in  object);   ! try  {}  catch  (e)  {} ... e funções

Slide 10

Slide 10 text

Existe uma main-thread para
 cada aba do navegador.

Slide 11

Slide 11 text

A main-thread é compartilhada por código JavaScript, cálculos de CSS, layout e painting.

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

ganhando aliados FLUXOS ASSÍNCRONOS

Slide 14

Slide 14 text

Tarefas que executam em paralelo sem interferir no fluxo principal.

Slide 15

Slide 15 text

Tarefas assíncronas geralmente regressam à main-thread no futuro.

Slide 16

Slide 16 text

Contador externo que permite condicionar a execução de código para o futuro. TIMERS setTimeout(callback,  3000);

Slide 17

Slide 17 text

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;

Slide 18

Slide 18 text

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);

Slide 19

Slide 19 text

Monitora a árvore do DOM e executa código com base em suas mudanças. MUTATION OBSERVER new  MutationObserver(callback);

Slide 20

Slide 20 text

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;

Slide 21

Slide 21 text

Estabelecem uma conexão permanente com o servidor para recebimento de dados. SERVER SENT EVENTS var  source  =  new  EventSource('addr');   source.onmessage  =  callback;

Slide 22

Slide 22 text

Executam uma porção de código em uma thread separada da principal. WEBWORKERS var  worker  =  new  Worker('addr.js');   worker.onmessage  =  callback;

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

Todos exemplos de código possuíam algo em comum!

Slide 25

Slide 25 text

$.get('products',  function  callback(data)  {      //...   });

Slide 26

Slide 26 text

Código passado como argumento
 para que seja executado em um
 tempo conveniente. CALLBACKS

Slide 27

Slide 27 text

O interpretador endereça a execução das callbacks através de um laço de eventos.

Slide 28

Slide 28 text

As APIs emitem um evento para indicar que o código da callback deve ser executado.

Slide 29

Slide 29 text

1. DETECÇÃO DE EVENTOS 2. TRATAMENTO DE UM EVENTO 2 1

Slide 30

Slide 30 text

registra callback dispara callback OPERAÇÃO ASSÍNCRONA

Slide 31

Slide 31 text

Tudo é executado em paralelo, exceto o seu código. - MIKITO TAKADA http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop

Slide 32

Slide 32 text

razões e maneiras QUEBRANDO O FLUXO DE EXECUÇÃO

Slide 33

Slide 33 text

ESCAPAR DOM EVENT BUBBLING do de um

Slide 34

Slide 34 text

QUEBRAR LONGAS de TAREFAS EXECUÇÕES

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

EMULAR ASSÍNCRONO comportamento

Slide 37

Slide 37 text

SETTIMEOUT Define um timer nulo que tão logo agenda uma tarefa na fila de eventos. ASSÍNCRONO COM * setTimeout(callback,  0);

Slide 38

Slide 38 text

5ª chamada

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

menos de 1ms

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

Suportada apenas no IE10* e node.js mas com alguns polyfills: • postMessage e MessageChannel • onreadystatechange • MutationObserver [*] IE10 bug - https://github.com/cujojs/when/issues/197 SETIMMEDIATE ASSÍNCRONO COM adeus aos timers

Slide 43

Slide 43 text

WEBWORKERS Código executando num ambiente separado: worker. Resultados são passados para o navegador através de callbacks. multithreads ASSÍNCRONO COM

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

Execução assíncrona no JavaScript é sobre código que utiliza callbacks.

Slide 47

Slide 47 text

Não existe nenhum outro mecanismo na linguagem 
 além deste.

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

solucionando o hell CALLBACKS

Slide 50

Slide 50 text

this.fetch(data,  function  ()  {      this.render();   }); X Contexto do this

Slide 51

Slide 51 text

this.fetch(data,  ()  =>  {      this.render();   }); use arrow functions

Slide 52

Slide 52 text

try  {      document.addEventListener('click',  ()  =>  {          //  ...          throw  new  Error('o/');      });   }  catch  (error)  {      handleError(error);   } X Tratamento de erros

Slide 53

Slide 53 text

document.addEventListener('click',  ()  =>  {      //  ...      handleError('o/');   }); aproveite as closures

Slide 55

Slide 55 text

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

Slide 57

Slide 57 text

SIMPLES PODEROSAS e

Slide 58

Slide 58 text

reais limitações CALLBACKS

Slide 59

Slide 59 text

APENAS UM EVENTO por CALLBACK

Slide 60

Slide 60 text

$.get('products',  function  callback(data)  {      callback2();      callback3();      callback4();   }); alto acoplamento X

Slide 61

Slide 61 text

ESTADO CALLBACKS NÃO MANTÊM

Slide 62

Slide 62 text

var products; ! $.get('products', function (data) { products = data; }); não há nada que uma global não resolva X

Slide 63

Slide 63 text

DIFÍCIL EVENTOS COORDENAR PARALELOS

Slide 64

Slide 64 text

$.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

Slide 65

Slide 65 text

uma alternativa PROMISES

Slide 66

Slide 66 text

Programação funcional é sobre trabalhar com valores e não com funções.

Slide 67

Slide 67 text

Uma promessa comumente representa o eventual resultado de uma operação assíncrona.

Slide 68

Slide 68 text

var  products  =  get('products');   ! products.then(function  onFulfilled()  {      //  succeeded   },  function  onRejected()  {      //  error   }); retorna uma promise

Slide 69

Slide 69 text

var  products  =  get('products');   ! products.then(function  onFulfilled()  {      //  succeeded   },  function  onRejected()  {      //  error   }); quando ou se já 
 tiver um valor...

Slide 70

Slide 70 text

É possível adicionar vários listeners a uma promessa.

Slide 71

Slide 71 text

products.then(callback1);   products.then(callback2);   products.then(callback3);

Slide 72

Slide 72 text

Promessas guardam estado e caso já resolvidas, a callback mesmo assim será invocado.

Slide 73

Slide 73 text

setTimeout(function  ()  {     products.then(function  ()  {        //  ...     });   },  9999); não tem como perder o bonde!

Slide 74

Slide 74 text

Promessas são um valor que pode ser passado para outras funções.

Slide 75

Slide 75 text

var  products  =  get('products');   ! var  basket  =  new  Basket(products);   var  list      =  new  ProductsList(products); argumento

Slide 76

Slide 76 text

.then

Slide 77

Slide 77 text

o cativeiro CRIANDO SUAS PRÓPRIAS PROMISES

Slide 78

Slide 78 text

new  Promise(function  (resolve,  reject)  {        if  (Math.random()  >  .5)  {              resolve('success');        }  else  {              reject('fail');        }   }

Slide 79

Slide 79 text

new  Promise(function  (resolve,  reject)  {        if  (Math.random()  >  .5)  {              resolve('success');        }  else  {              reject('fail');        }   } sucesso

Slide 80

Slide 80 text

new  Promise(function  (resolve,  reject)  {        if  (Math.random()  >  .5)  {              resolve('success');        }  else  {              reject('fail');        }   } falha

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

resolve() reject()

Slide 86

Slide 86 text

Promise.promisify(libraryFunction); https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns aproveite todos
 os recursos Promisify

Slide 87

Slide 87 text

$.get('test.php').then(      function()  {          alert('$.get  succeeded');      },  function()  {          alert('$.get  failed!');      }   ); jQuery entende* promises * aguarde, falaremos mais a respeito

Slide 88

Slide 88 text

encadeando promessas CHAINING

Slide 89

Slide 89 text

A popularização de chaining no JavaScript é devido em grande parte a jQuery.

Slide 90

Slide 90 text

$('[data-­‐menu]')      .css('opacity',  0)      .fadeIn('fast')      .addClass('active')      .remove(); chaining!

Slide 91

Slide 91 text

parser.start()     .then(parser.getFiles)     .then(parser.generateIndex)     .then(parser.generatePosts); https://github.com/es6rocks/harmonic pega os arquivos

Slide 92

Slide 92 text

parser.start()     .then(parser.getFiles)     .then(parser.generateIndex)     .then(parser.generatePosts); https://github.com/es6rocks/harmonic utiliza os
 arquivos

Slide 93

Slide 93 text

O encadeamento é análogo a uma linha de montagem.

Slide 94

Slide 94 text

parser.start()      .then(function  ()  {        return  getFiles();     })     .then(function  ()  {       //  ...     });

Slide 95

Slide 95 text

parser.start()      .then(function  ()  {        return  getFiles();     })     .then(function  ()  {       //  ...     }); espera por getFiles

Slide 96

Slide 96 text

like a boss TRATAMENTO DE ERRO

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

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?

Slide 103

Slide 103 text

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"

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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?

Slide 107

Slide 107 text

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

Slide 108

Slide 108 text

throw

Slide 109

Slide 109 text

coordenando PARALELISMO

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

Promise.race([      get('gifts'),        get('products')   ])      .then(function  (results)  {          //  first  resolved      },  function  (result)  {          //  first  rejected      }); uma corrida?!

Slide 114

Slide 114 text

Promise.race([      get('gifts'),        get('products')   ])      .then(function  (results)  {          //  first  resolved      },  function  (result)  {          //  or  first  rejected      }); primeiro 
 que terminar

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

• 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'));

Slide 117

Slide 117 text

No content

Slide 118

Slide 118 text

um bônus GENERATORS

Slide 119

Slide 119 text

Trata-se de uma função que constrói uma coleção 
 sob demanda.

Slide 120

Slide 120 text

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

Slide 121

Slide 121 text

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

Slide 122

Slide 122 text

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

Slide 123

Slide 123 text

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

Slide 124

Slide 124 text

com GENERATORS PROMISES

Slide 125

Slide 125 text

Abstração que encapsula um generator que retorna uma coleção de promises.

Slide 126

Slide 126 text

A cada resolução de uma promise, o next do generator é executado.

Slide 127

Slide 127 text

O generator deve criar e retorna uma próxima promise ou valor.

Slide 128

Slide 128 text

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]);   })();

Slide 129

Slide 129 text

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...

Slide 130

Slide 130 text

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]);   })();

Slide 131

Slide 131 text

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!

Slide 132

Slide 132 text

No content

Slide 133

Slide 133 text

[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

Slide 134

Slide 134 text

Promises mean having enough memory to keep data around. - DREW CRAWFORD http://sealedabstract.com/code/broken-promises Haters gonna hate. - 1º COMENTÁRIO

Slide 135

Slide 135 text

Não existe bala de prata, cada caso tem suas particularidades.

Slide 136

Slide 136 text

Callbacks e promises envolvem conceitos importantes que você deve conhecer.

Slide 137

Slide 137 text

yo, rock 'n' roll OBRIGADO A TODOS