Back to the future: Async JS handling

We talk about JavaScript. Each month in Warsaw, Poland.

Speaker

Maciej Pawluk

"Back to the future - Async JS handling"

2016-06-08

pawluk.mm@gmail.com

"LATER" is not always followed by "NOW"

            
                var counter = 0;
                setTimeout(() => counter++, 0);
                console.log(counter);
            
        

Use case: Login Page

  1. User enters his login and password
  2. User object is fetched form the database
  3. We calculate hash value based on the password and user.salt
  4. If hash equals user.hash - user is logged in

Callbacks

            
                getUser(
                  login, password, cb1(err, user) {
                    if(!err) {
                      calculateHash(
                        password, user.salt, cb2(hash) {
                           if(user.hash != hash) {
                             throw new Error('Incorrect password');
                           }
                      });
                }});
            
        
            
                listen('click', function handler() {
                  setTimeout(function request() {
                    ajax('http://url.1', function (text) {
                      ajax('http://url.1'+text, function (text) {
                        if(text === 'hello') {
                          handler();
                        }
                        else if(text === 'word') {
                          request();
                        }
                } }); }, 500); });
            
        

Callbacks

            
                getUser(
                  login, password, cb1(err, user) {
                    if(!err) {
                      calculateHash(
                        password, user.salt, cb2(hash) {
                           if(user.hash != hash) {
                             throw new Error('Incorrect password');
                           }
                      });
                }});
            
        

Promises

            
                Promise.resolve(p)
                  .then(
                    function fulfilled(val) { },
                    function  rejected(err) { }
                );

            
        

Promises

            
                getUser(login, password)
                  .then(user => Promise.all(
                    user, calculateHash(password, user.salt)
                  ))
                  .then(([user, hash]) => {
                    if(user.hash != hash) {
                      throw new Error('Incorrect password');
                  }})
                  .catch(err => { ... });
            
        

Generators

            
                function *generator() {
                  var x = 1 + (yield "Inner")
                  return x;
                }

            
        

Generators

            
                function *generator() {
                  var x = 1 + (yield "Inner")
                  return x;
                }
                var it = generator();
                it.next();   //{done: false, value: "Inner"}
                it.next(43); //{done: true, value: 44}
            
        

"Yield" keyword

Designed by Freepik

"Yield" keyword

Designed by Freepik
            
                function *orderItem() {
                  var item = yield getItem(
                    {itemId: 21, paid: true}
                  );
                }
            
        
            
                //it - orderItem() iterator

                function getItem(itemDetails) {
                  ajax(item)
                    .then(
                      item => it.next(data),
                      err  => it.throw(err)
                  );
                };
            
        
            
                function *loginUser(login, password) {
                  var user = yield getUser(login, password);
                  var hash = yield calculateHash(
                    password, user.salt
                  );
                  if (user.hash !== hash) ...
                });
                asyncRun(loginUser("JohnDoe", "secret123!"));
            
        

A little bit of ES2017...

            
                async function loginUser(login, password) {
                  var user = await getUser(login, password);
                  var hash = await calculateHash(
                    password, user.salt
                  );
                  if (user.hash !== hash) ...
                });
                loginUser("JohnDoe", "secret123!")
                  .catch(err => { ... });
            
        

Sources:

  1. promisejs.org
  2. You Don't Know Js - Async & Performance
  3. Why I'm not waiting for async/await

Thank you!