SlideShare a Scribd company logo
Callbacks, Promises, and Coroutines
                  (oh my!)


     Asynchronous Programming
        Patterns in JavaScript


                Domenic Denicola
           http://domenicdenicola.com
                @domenicdenicola
In non-web languages,
most of the code we write is synchronous.

                aka blocking
Console.WriteLine("What is your name?");
string name = Console.ReadLine();
Console.WriteLine("Hello, " + name);
var fileNames = Directory.EnumerateFiles("C:");

foreach (var fileName in fileNames)
{
  using (var f = File.Open(fileName, FileMode.Open))
  {
    Console.WriteLine(fileName + " " + f.Length);
  }
}
using (var client = new WebClient())
{
  string html =
client.DownloadString("http://news.ycombinator.com");

    Console.WriteLine(html.Contains("Google"));
    Console.WriteLine(html.Contains("Microsoft"));
    Console.WriteLine(html.Contains("Apple"));
}
Thread.Start                               BackgroundWorker


               Control.InvokeRequired



        This often causes us some pain…

       … but hey, there’s always threads!

                       Dispatcher.Invoke



ThreadPool

                                              .AsParallel()
Q: What are these threads doing, most of the time?


A: waiting
WTF!?
In JavaScript, we do things differently.
There’s only one thread in JavaScript,
so we use that thread to get stuff done.
OK, let’s talk about…
•   The event loop
•   Callbacks
•   Promises
•   Coroutines
THE EVENT LOOP
You’ve seen event loops before:
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
  MSG msg;
  while (GetMessage(&msg, NULL, 0, 0) > 0)
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return msg.wParam;
}
this.btnOK.Click += this.btnOK_Click;


private void btnOK_Click(object sender,
                         EventArgs e)
{
  // ...
}
$("#ok-button").click(function () {
    // ...
});

setTimeout(function () {
    // ...
}, 100);

$.get("http://example.com", function (result) {
    // ...
});
Some event loop subtleties
•   Yielding
•   Async’s not sync
•   Errors
•   It’s not magic
Event Loop Subtleties

   Yielding
   console.log("1");

   $.get("/echo/2", function (result) {
     console.log(result);
   });

   console.log("3");

   // 1, 3, 2
Event Loop Subtleties

   Async’s not sync
   var hi = null;

   $.get("/echo/hi", function (result) {
     hi = result;
   });

   console.log(hi);

   // null
Event Loop Subtleties

   Errors
   console.log("About to get the website...");

   $.ajax("http://sometimesdown.example.com", {
     success: function (result) {
        console.log(result);
     },
     error: function () {
        throw new Error("Error getting the website");
     }
   });

   console.log("Continuing about my business...");
Event Loop Subtleties

   It’s not magic
   function fib(n) {
       return n < 2 ? 1 : fib(n-2) + fib(n-1);
   }

   console.log("1");

   setTimeout(function () {
      console.log("2");
   }, 100);

   fib(40);

   // 1 ... 15 seconds later ... 2

http://teddziuba.com/2011/10/node-js-is-cancer.html
The event loop is tricky… but powerful.
CALLBACKS
What we’ve seen so far has been doing
  asynchronicity through callbacks.
Callbacks are OK for simple operations, but
 force us into continuation passing style.
Recurring StackOverflow question:
function getY() {
  var y;
  $.get("/gety", function (jsonData) {
    y = jsonData.y;
  });
  return y;
}
                      Why doesn’t it work???
var x = 5;
var y = getY();

console.log(x + y);
After getting our data, we have to do
 everything else in a continuation:
function getY(continueWith) {
    $.get("/gety", function (jsonData) {
      continueWith(jsonData.y);
    });
}


var x = 5;
getY(function (y) {
    console.log(x + y);
});
CPS Headaches
• Doing things in sequence is hard
• Doing things in parallel is harder
• Errors get lost easily
CPS Headaches

  Doing things in sequence is hard
  $("#button").click(function () {
    promptUserForTwitterHandle(function (handle) {
      twitter.getTweetsFor(handle, function (tweets) {
        ui.show(tweets);
      });
    });
  });
CPS Headaches

  Doing things in parallel is harder
  var tweets, answers, checkins;

  twitter.getTweetsFor("domenicdenicola", function (result) {
    tweets = result;
    somethingFinished();
  });
  stackOverflow.getAnswersFor("Domenic", function (result) {
    answers = result;
    somethingFinished();
  });
  fourSquare.getCheckinsBy("Domenic", function (result) {
    checkins = result;
    somethingFinished();
  });
CPS Headaches

  Doing things in parallel is harder
  var finishedSoFar = 0;

  function somethingFinished() {
    if (++finishedSoFar === 3) {
      ui.show(tweets, answers, checkins);
    }
  }
CPS Headaches

  Errors get lost easily
  function getTotalFileLengths(path, callback) {
    fs.readdir(path, function (err, fileNames) {
      var total = 0;

       var finishedSoFar = 0;
       function finished() {
         if (++finishedSoFar === fileNames.length) {
           callback(total);
         }
       }

        fileNames.forEach(function (fileName) {
          fs.readFile(fileName, function (err, file) {
            total += file.length;
            finished();
          });
        });
      });
  }
You could write your own library to make this nicer…
function parallel(actions, callback) {
  var results = [];
  function finished(result) {
    results.push(result);
    if (results.length === actions.length) {
        callback(results);
    }
  }

    actions.forEach(function (action) {
      action(finished);
    });
}
parallel([
  function (cb) {
     twitter.getTweetsFor("domenicdenicola", cb);
  },
  function (cb) {
     stackOverflow.getAnswersFor("Domenic", cb);
  },
  function (cb) {
     fourSquare.getCheckinsFor("Domenic", cb);
  }
], function (results) {
  console.log("tweets = ", results[0]);
  console.log("answers = ", results[1]);
  console.log("checkins = ", results[2]);
});
And in fact many people have:




https://github.com/joyent/node/wiki/modules#wiki-async-flow
The best of these (IMO) are based on
  an abstraction called “promises”
PROMISES
Un-inverts the chain of responsibility:
instead of calling a passed callback, return a promise.
addWithCallback(a, b, function (result) {
  assert.equal(result, a + b);
});

var promise = addWithPromise(a, b);

promise.then(function (result) {
  assert.equal(result, a + b);
});
Why promises are awesome

• Cleaner method signatures
• Uniform return/error semantics
• Easy composition
• Easy sequential/parallel join
• Always async
• Exception-style error bubbling
Promises are Awesome

  Cleaner method signatures
  Uniform return/error semantics
  $.get(
    url,
    [data],
    [success(data, status, xhr)],
    [dataType]
  )
Promises are Awesome

  Cleaner method signatures
  Uniform return/error semantics
  $.ajax(url, settings)

  settings.success(data, status, xhr)
  settings.error(xhr, status, errorThrown)
  settings.complete(xhr, status)
Promises are Awesome

  Cleaner method signatures
  Uniform return/error semantics
  fs.open(
    path,
    flags,
    [mode],
    [callback(error, file)]
  )
Promises are Awesome

  Cleaner method signatures
  Uniform return/error semantics
  fs.write(
    file,
    buffer,
    offset,
    length,
    position,
    [callback(error, written, buffer)]
  )
Promises are Awesome

  Cleaner method signatures
  Uniform return/error semantics
  getAsPromise(url, [data], [dataType]).then(
    function onFulfilled(result) {
       var data = result.data;
       var status = result.status;
       var xhr = result.xhr;
    },
    function onBroken(error) {
       console.error("Couldn't get", error);
    }
  );
Promises are Awesome

  Easy composition

  function getUser(userName, onSuccess, onError) {
    $.ajax("/user?" + userName, {
      success: onSuccess,
      error: onError
    });
  }
Promises are Awesome

  Easy composition

  function getUser(userName) {
    return getAsPromise("/user?" + userName);
  }
Promises are Awesome

  Easy composition

  function getFirstName(userName, onSuccess, onError) {
    $.ajax("/user?" + userName, {
      success: function successProxy(data) {
         onSuccess(data.firstName);
      },
      error: onError
    });
  }
Promises are Awesome

  Easy composition

  function getFirstName(userName) {
    return getAsPromise("/user?" + userName)
             .get("firstName");
  }
Promises are Awesome

  Easy sequential join

  $("#button").click(function () {
    promptUserForTwitterHandle(function (handle) {
      twitter.getTweetsFor(handle, function (tweets) {
        ui.show(tweets);
      });
    });
  });
Promises are Awesome

  Easy sequential join

  $("#button").clickPromise()
    .then(promptUserForTwitterHandle)
    .then(twitter.getTweetsFor)
    .then(ui.show);
Promises are Awesome

  Easy parallel join

  var tweets, answers, checkins;

  twitter.getTweetsFor("domenicdenicola", function (result) {
    tweets = result;
    somethingFinished();
  });
  stackOverflow.getAnswersFor("Domenic", function (result) {
    answers = result;
    somethingFinished();
  });
  fourSquare.getCheckinsBy("Domenic", function (result) {
    checkins = result;
    somethingFinished();
  });
Promises are Awesome

  Easy parallel join

  Q.all([
    twitter.getTweetsFor("domenicdenicola"),
    stackOverflow.getAnswersFor("Domenic"),
    fourSquare.getCheckinsBy("Domenic")
  ]).then(function (results) {
    console.log(results[0], results[1], results[2]);
  });
Promises are Awesome

  Easy parallel join

  Q.all([
    twitter.getTweetsFor("domenicdenicola"),
    stackOverflow.getAnswersFor("Domenic"),
    fourSquare.getCheckinsBy("Domenic")
  ]).spread(function (tweets, answers, checkins) {
    console.log(tweets, answers, checkins);
  });
Promises are Awesome

  Always async

  function getUser(userName, onSuccess, onError) {
    if (cache.has(userName)) {
      onSuccess(cache.get(userName));
    } else {
      $.ajax("/user?" + userName, {
        success: onSuccess,
        error: onError
      });
    }
  }
Promises are Awesome

  Always async

  console.log("1");

  getUser("ddenicola", function (user) {
    console.log(user.firstName);
  });

  console.log("2");

  // 1, 2, Domenic
Promises are Awesome

  Always async

  console.log("1");

  getUser("ddenicola", function (user) {
    console.log(user.firstName);
  });

  console.log("2");

  // 1, Domenic, 2
Promises are Awesome

  Always async

  function getUser(userName) {
    if (cache.has(userName)) {
      return Q.ref(cache.get(userName));
    } else {
      return getWithPromise("/user?" + userName);
    }
  }
Promises are Awesome

  Always async

  console.log("1");

  getUser("ddenicola").then(function (user) {
    console.log(user.firstName);
  });

  console.log("2");

  // 1, 2, Domenic (every time)
Promises are Awesome

  Exception-style error bubbling

  getUser("Domenic", function (user) {
    getBestFriend(user, function (friend) {
      ui.showBestFriend(friend);
    });
  });
Promises are Awesome

  Exception-style error bubbling

  getUser("Domenic", function (err, user) {
    if (err) {
      ui.error(err);
    } else {
      getBestFriend(user, function (err, friend) {
        if (err) {
          ui.error(err);
        } else {
          ui.showBestFriend(friend);
        }
      });
    }
  });
Promises are Awesome

  Exception-style error bubbling

  getUser("Domenic")
    .then(getBestFriend, ui.error)
    .then(ui.showBestFriend, ui.error);
Promises are Awesome

  Exception-style error bubbling

  getUser("Domenic")
    .then(getBestFriend)
    .then(ui.showBestFriend, ui.error);
Promises are Awesome

  Exception-style error bubbling

  ui.startSpinner();
  getUser("Domenic")
    .then(getBestFriend)
    .then(
       function (friend) {
          ui.showBestFriend(friend);
          ui.stopSpinner();
       },
       function (error) {
          ui.error(error);
          ui.stopSpinner();
       }
    );
Promises are Awesome

  Exception-style error bubbling

  ui.startSpinner();
  getUser("Domenic")
    .then(getBestFriend)
    .then(ui.showBestFriend, ui.error)
    .fin(ui.stopSpinner);
Promises are Awesome

  Exception-style error bubbling

  function getBestFriendAndDontGiveUp(user) {
    return getUser(user).then(
      getBestFriend,
      function (error) {
        if (error instanceof TemporaryNetworkError) {
          console.log("Retrying after error", error);
          return getBestFriendAndDontGiveUp(user);
        }
        throw error;
      });
  }
Sounds great. How do I get in on this action?
Use Q
•   By Kris Kowal, @kriskowal
•   https://github.com/kriskowal/q
•   Can consume promises from jQuery etc.
•   Implements various CommonJS standards
If you’re already using jQuery’s promises, switch to Q:


    https://github.com/kriskowal/q/wiki/jQuery
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patterns in JavaScript
Creating promises with Q

   Fulfilling promises
   // We have:
   setTimeout(doSomething, 1000);

   // We want:
   delay(1000).then(doSomething);
Creating promises with Q

   Fulfilling promises
   function delay(ms) {
     var deferred = Q.defer();
     setTimeout(deferred.resolve, ms);
     return deferred.promise;
   }

   delay(1000).then(doSomething);
Creating promises with Q

   Breaking promises
   function getWithTimeout(url, ms, onSuccess, onError) {
     var isTimedOut = false, isHttpErrored = false;

       setTimeout(function () {
         if (!isHttpErrored) {
           isTimedOut = true;
           onError(new Error("timed out"));
         }
       }, ms);

       $.ajax(url, {
         success: function (result) {
           if (!isTimedOut) { onSuccess(result); }
         },
         error: function (xhr, status, error) {
           if (!isTimedOut) {
             isHttpErrored = true;
             onError(error);
           }
         }
       });
   }
Creating promises with Q

   Breaking promises
   function getWithTimeout(url, ms) {
     var deferred = Q.defer();

       setTimeout(function () {
         deferred.reject(new Error("timed out"));
       }, ms);

       $.ajax(url, {
         success: deferred.resolve,
         error: deferred.reject
       });

       return deferred.promise;
   }
Creating promises with Q

   Building abstractions
   function timeout(promise, ms) {
     var deferred = Q.defer();
     promise.then(deferred.resolve, deferred.reject);

       setTimeout(function () {
         deferred.reject(new Error("timed out"));
       }, ms);

       return deferred.promise;
   }

   function getWithTimeout(url, ms) {
     return timeout(getAsPromise(url), ms);
   }
Promises are cool.
They clean up our method signatures.


They’re composable, they’re joinable,
    and they’re dependably async.


They unify various callback conventions
 into something very much like return
        values and exceptions.
But… we still have to write in CPS.
COROUTINES
“Coroutines are computer program
            components that generalize subroutines
                 to allow multiple entry points for
             suspending and resuming execution at
                             certain locations.”



http://en.wikipedia.org/wiki/Coroutine
WTF!?
Nice:
var xP = getX();
var yP = getY();
var zP = getZ();

Q.all([xP, yP, zP]).spread(function (x, y, z) {
  console.log(x + y + z);
});
Nicer:
var [x, y, z] = await Q.all([getX(), getY(), getZ()]);

console.log(x + y + z);
Nice:
$("#button").clickPromise()
  .then(promptUserForTwitterHandle)
  .then(twitter.getTweetsFor)
  .then(ui.show);
Nicer:
await $("#button").clickPromise();

var handle = await promptUserForTwitterHandle();
var tweets = await twitter.getTweetsFor(handle);

ui.show(tweets);
Q: Can’t the compiler do this for me?


A: yes… if you are willing to introduce a compiler.
Several options, none perfect
•   Kaffeine: http://weepy.github.com/kaffeine/
•   Traceur: http://tinyurl.com/traceur-js
•   TameJS: http://tamejs.org/
•   Node fork: http://tinyurl.com/node-async
Q: OK well… can’t the interpreter do this for me?


A: yes… if you’re willing to wait for the next version of JS.
The next version of JavaScript (“ECMAScript
Harmony”) has a limited form of coroutines that can
  be twisted to do something like what we want.
ECMAScript Harmony generators
 function* fibonacci() {
   var [prev, curr] = [0, 1];
   for (;;) {
     [prev, curr] = [curr, prev + curr];
      yield curr;
   }
 }

 for (n of fibonnaci()) {
   console.log(n);
 }



http://wiki.ecmascript.org/doku.php?id=harmony:generators
ECMAScript Harmony generators
 var eventualAdd = Q.async(function* (pA, pB) {
   var a = yield pA;
   var b = yield pB;
   return a + b;
 });




https://github.com/kriskowal/q/tree/master/examples/async-generators
ECMAScript Harmony generators
 // Can only use yield as we want to within
 // Q.async'ed generator functions

 Q.async(function* () {
   // Talk to the server to get one and two.
   var three = yield eventualAdd(getOne(), getTwo());

   assert.equal(three, 3);
 })();




https://groups.google.com/d/topic/q-continuum/7PWKbgeFA48/discussion
ECMAScript Harmony generators
 // Given promise-returning delay(ms) as before:

 var animateAsync = Q.async(function* (el) {
   for (var i = 0; i < 100; ++i) {
     element.style.left = i;
     yield delay(20);
   }
 });




http://wiki.ecmascript.org/doku.php?id=strawman:async_functions
ECMAScript Harmony generators
 Q.async(function* () {
   var el = document.getElementById("my-element");

    yield animateAsync(el);

   console.log("it's done animating");
 })();




https://groups.google.com/d/topic/q-continuum/7PWKbgeFA48/discussion
So coroutines are a bit of a mess, but
   we’ll see how things shape up.
Recap
•   Async is here to stay
•   But you don’t have to dive into callback hell
•   Use promises
•   Use Q
•   Maybe use coroutines if you’re feeling brave
Thanks for listening!

More Related Content

What's hot

Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJS
Abul Hasan
 
Rust
RustRust
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
경원 이
 
All you need to know about the JavaScript event loop
All you need to know about the JavaScript event loopAll you need to know about the JavaScript event loop
All you need to know about the JavaScript event loop
Saša Tatar
 
Clean code and Code Smells
Clean code and Code SmellsClean code and Code Smells
Clean code and Code Smells
Mario Sangiorgio
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우
Arawn Park
 
[수정본] 우아한 객체지향
[수정본] 우아한 객체지향[수정본] 우아한 객체지향
[수정본] 우아한 객체지향
Young-Ho Cho
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017
Roman Elizarov
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous Javascript
Garrett Welson
 
Promises, Promises
Promises, PromisesPromises, Promises
Promises, Promises
Domenic Denicola
 
Optional in Java 8
Optional in Java 8Optional in Java 8
Optional in Java 8
Richard Walker
 
JavaScript Event Loop
JavaScript Event LoopJavaScript Event Loop
JavaScript Event Loop
Thomas Hunter II
 
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
용근 권
 
Nouveautés Java 9-10-11
Nouveautés Java 9-10-11Nouveautés Java 9-10-11
Nouveautés Java 9-10-11
Mahamadou TOURE, Ph.D.
 
Angular and The Case for RxJS
Angular and The Case for RxJSAngular and The Case for RxJS
Angular and The Case for RxJS
Sandi Barr
 
Asynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & PromisesAsynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & Promises
Hùng Nguyễn Huy
 
React new features and intro to Hooks
React new features and intro to HooksReact new features and intro to Hooks
React new features and intro to Hooks
Soluto
 
Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFuture
José Paumard
 
Introduction to Rust language programming
Introduction to Rust language programmingIntroduction to Rust language programming
Introduction to Rust language programming
Rodolfo Finochietti
 
[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기
[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기
[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기
Chanwoong Kim
 

What's hot (20)

Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJS
 
Rust
RustRust
Rust
 
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
 
All you need to know about the JavaScript event loop
All you need to know about the JavaScript event loopAll you need to know about the JavaScript event loop
All you need to know about the JavaScript event loop
 
Clean code and Code Smells
Clean code and Code SmellsClean code and Code Smells
Clean code and Code Smells
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우
 
[수정본] 우아한 객체지향
[수정본] 우아한 객체지향[수정본] 우아한 객체지향
[수정본] 우아한 객체지향
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous Javascript
 
Promises, Promises
Promises, PromisesPromises, Promises
Promises, Promises
 
Optional in Java 8
Optional in Java 8Optional in Java 8
Optional in Java 8
 
JavaScript Event Loop
JavaScript Event LoopJavaScript Event Loop
JavaScript Event Loop
 
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
 
Nouveautés Java 9-10-11
Nouveautés Java 9-10-11Nouveautés Java 9-10-11
Nouveautés Java 9-10-11
 
Angular and The Case for RxJS
Angular and The Case for RxJSAngular and The Case for RxJS
Angular and The Case for RxJS
 
Asynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & PromisesAsynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & Promises
 
React new features and intro to Hooks
React new features and intro to HooksReact new features and intro to Hooks
React new features and intro to Hooks
 
Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFuture
 
Introduction to Rust language programming
Introduction to Rust language programmingIntroduction to Rust language programming
Introduction to Rust language programming
 
[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기
[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기
[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기
 

Viewers also liked

W3C Automotive 표준 개발 현황
W3C Automotive 표준 개발 현황W3C Automotive 표준 개발 현황
W3C Automotive 표준 개발 현황
Wonsuk Lee
 
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
정석 양
 
[하코사세미나] 한 시간 만에 배우는 Jquery
[하코사세미나] 한 시간 만에 배우는 Jquery[하코사세미나] 한 시간 만에 배우는 Jquery
[하코사세미나] 한 시간 만에 배우는 Jquery
정석 양
 
[ 하코사세미나] 의외로 쉬운 D3 그래프 퍼블리싱
[ 하코사세미나] 의외로 쉬운 D3 그래프 퍼블리싱[ 하코사세미나] 의외로 쉬운 D3 그래프 퍼블리싱
[ 하코사세미나] 의외로 쉬운 D3 그래프 퍼블리싱
정석 양
 
CSS 실무테크닉
CSS 실무테크닉CSS 실무테크닉
CSS 실무테크닉
Eun Cho
 
CSS 셀렉터
CSS 셀렉터CSS 셀렉터
CSS 셀렉터
Eun Cho
 
[Hello world 오픈세미나]실시간웹을위한comet과socket.io
[Hello world 오픈세미나]실시간웹을위한comet과socket.io[Hello world 오픈세미나]실시간웹을위한comet과socket.io
[Hello world 오픈세미나]실시간웹을위한comet과socket.io
NAVER D2
 
[Hello world 오픈 세미나]ffmpeg android
[Hello world 오픈 세미나]ffmpeg android[Hello world 오픈 세미나]ffmpeg android
[Hello world 오픈 세미나]ffmpeg androidNAVER D2
 
[Hello world 오픈 세미나]oauth
[Hello world 오픈 세미나]oauth[Hello world 오픈 세미나]oauth
[Hello world 오픈 세미나]oauthNAVER D2
 

Viewers also liked (9)

W3C Automotive 표준 개발 현황
W3C Automotive 표준 개발 현황W3C Automotive 표준 개발 현황
W3C Automotive 표준 개발 현황
 
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
 
[하코사세미나] 한 시간 만에 배우는 Jquery
[하코사세미나] 한 시간 만에 배우는 Jquery[하코사세미나] 한 시간 만에 배우는 Jquery
[하코사세미나] 한 시간 만에 배우는 Jquery
 
[ 하코사세미나] 의외로 쉬운 D3 그래프 퍼블리싱
[ 하코사세미나] 의외로 쉬운 D3 그래프 퍼블리싱[ 하코사세미나] 의외로 쉬운 D3 그래프 퍼블리싱
[ 하코사세미나] 의외로 쉬운 D3 그래프 퍼블리싱
 
CSS 실무테크닉
CSS 실무테크닉CSS 실무테크닉
CSS 실무테크닉
 
CSS 셀렉터
CSS 셀렉터CSS 셀렉터
CSS 셀렉터
 
[Hello world 오픈세미나]실시간웹을위한comet과socket.io
[Hello world 오픈세미나]실시간웹을위한comet과socket.io[Hello world 오픈세미나]실시간웹을위한comet과socket.io
[Hello world 오픈세미나]실시간웹을위한comet과socket.io
 
[Hello world 오픈 세미나]ffmpeg android
[Hello world 오픈 세미나]ffmpeg android[Hello world 오픈 세미나]ffmpeg android
[Hello world 오픈 세미나]ffmpeg android
 
[Hello world 오픈 세미나]oauth
[Hello world 오픈 세미나]oauth[Hello world 오픈 세미나]oauth
[Hello world 오픈 세미나]oauth
 

Similar to Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patterns in JavaScript

Pick up the low-hanging concurrency fruit
Pick up the low-hanging concurrency fruitPick up the low-hanging concurrency fruit
Pick up the low-hanging concurrency fruit
Vaclav Pech
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
Michael Girouard
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
rajivmordani
 
mobl - model-driven engineering lecture
mobl - model-driven engineering lecturemobl - model-driven engineering lecture
mobl - model-driven engineering lecture
zefhemel
 
Promise: async programming hero
Promise: async programming heroPromise: async programming hero
Promise: async programming hero
The Software House
 
Sane Async Patterns
Sane Async PatternsSane Async Patterns
Sane Async Patterns
TrevorBurnham
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScript
jnewmanux
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in Swift
Peter Friese
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
Adam L Barrett
 
mobl
moblmobl
mobl
zefhemel
 
Javascript Frameworks for Joomla
Javascript Frameworks for JoomlaJavascript Frameworks for Joomla
Javascript Frameworks for Joomla
Luke Summerfield
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
Dmitry Sheiko
 
The Promised Land (in Angular)
The Promised Land (in Angular)The Promised Land (in Angular)
The Promised Land (in Angular)
Domenic Denicola
 
Node.js - Best practices
Node.js  - Best practicesNode.js  - Best practices
Node.js - Best practices
Felix Geisendörfer
 
ES6 - Next Generation Javascript
ES6 - Next Generation JavascriptES6 - Next Generation Javascript
ES6 - Next Generation Javascript
RameshNair6
 
JavaScript Lessons 2023
JavaScript Lessons 2023JavaScript Lessons 2023
JavaScript Lessons 2023
Laurence Svekis ✔
 
ES6: The Awesome Parts
ES6: The Awesome PartsES6: The Awesome Parts
ES6: The Awesome Parts
Domenic Denicola
 
Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13
Jason Lotito
 
Angular promises and http
Angular promises and httpAngular promises and http
Angular promises and http
Alexe Bogdan
 
Griffon @ Svwjug
Griffon @ SvwjugGriffon @ Svwjug
Griffon @ Svwjug
Andres Almiray
 

Similar to Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patterns in JavaScript (20)

Pick up the low-hanging concurrency fruit
Pick up the low-hanging concurrency fruitPick up the low-hanging concurrency fruit
Pick up the low-hanging concurrency fruit
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
 
mobl - model-driven engineering lecture
mobl - model-driven engineering lecturemobl - model-driven engineering lecture
mobl - model-driven engineering lecture
 
Promise: async programming hero
Promise: async programming heroPromise: async programming hero
Promise: async programming hero
 
Sane Async Patterns
Sane Async PatternsSane Async Patterns
Sane Async Patterns
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScript
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in Swift
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
 
mobl
moblmobl
mobl
 
Javascript Frameworks for Joomla
Javascript Frameworks for JoomlaJavascript Frameworks for Joomla
Javascript Frameworks for Joomla
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
The Promised Land (in Angular)
The Promised Land (in Angular)The Promised Land (in Angular)
The Promised Land (in Angular)
 
Node.js - Best practices
Node.js  - Best practicesNode.js  - Best practices
Node.js - Best practices
 
ES6 - Next Generation Javascript
ES6 - Next Generation JavascriptES6 - Next Generation Javascript
ES6 - Next Generation Javascript
 
JavaScript Lessons 2023
JavaScript Lessons 2023JavaScript Lessons 2023
JavaScript Lessons 2023
 
ES6: The Awesome Parts
ES6: The Awesome PartsES6: The Awesome Parts
ES6: The Awesome Parts
 
Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13
 
Angular promises and http
Angular promises and httpAngular promises and http
Angular promises and http
 
Griffon @ Svwjug
Griffon @ SvwjugGriffon @ Svwjug
Griffon @ Svwjug
 

More from Domenic Denicola

The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)
Domenic Denicola
 
Async Frontiers
Async FrontiersAsync Frontiers
Async Frontiers
Domenic Denicola
 
The jsdom
The jsdomThe jsdom
The jsdom
Domenic Denicola
 
The Final Frontier
The Final FrontierThe Final Frontier
The Final Frontier
Domenic Denicola
 
ES6 in Real Life
ES6 in Real LifeES6 in Real Life
ES6 in Real Life
Domenic Denicola
 
Streams for the Web
Streams for the WebStreams for the Web
Streams for the Web
Domenic Denicola
 
After Return of the Jedi
After Return of the JediAfter Return of the Jedi
After Return of the Jedi
Domenic Denicola
 
The State of JavaScript
The State of JavaScriptThe State of JavaScript
The State of JavaScript
Domenic Denicola
 
How to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards BodiesHow to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards Bodies
Domenic Denicola
 
The Extensible Web
The Extensible WebThe Extensible Web
The Extensible Web
Domenic Denicola
 
Boom! Promises/A+ Was Born
Boom! Promises/A+ Was BornBoom! Promises/A+ Was Born
Boom! Promises/A+ Was Born
Domenic Denicola
 
Domains!
Domains!Domains!
Client-Side Packages
Client-Side PackagesClient-Side Packages
Client-Side Packages
Domenic Denicola
 
Creating Truly RESTful APIs
Creating Truly RESTful APIsCreating Truly RESTful APIs
Creating Truly RESTful APIs
Domenic Denicola
 
JavaScript on the Desktop
JavaScript on the DesktopJavaScript on the Desktop
JavaScript on the Desktop
Domenic Denicola
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
Domenic Denicola
 
Real World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScriptReal World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScript
Domenic Denicola
 
Unit Testing for Great Justice
Unit Testing for Great JusticeUnit Testing for Great Justice
Unit Testing for Great Justice
Domenic Denicola
 
Understanding the Node.js Platform
Understanding the Node.js PlatformUnderstanding the Node.js Platform
Understanding the Node.js Platform
Domenic Denicola
 

More from Domenic Denicola (19)

The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)
 
Async Frontiers
Async FrontiersAsync Frontiers
Async Frontiers
 
The jsdom
The jsdomThe jsdom
The jsdom
 
The Final Frontier
The Final FrontierThe Final Frontier
The Final Frontier
 
ES6 in Real Life
ES6 in Real LifeES6 in Real Life
ES6 in Real Life
 
Streams for the Web
Streams for the WebStreams for the Web
Streams for the Web
 
After Return of the Jedi
After Return of the JediAfter Return of the Jedi
After Return of the Jedi
 
The State of JavaScript
The State of JavaScriptThe State of JavaScript
The State of JavaScript
 
How to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards BodiesHow to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards Bodies
 
The Extensible Web
The Extensible WebThe Extensible Web
The Extensible Web
 
Boom! Promises/A+ Was Born
Boom! Promises/A+ Was BornBoom! Promises/A+ Was Born
Boom! Promises/A+ Was Born
 
Domains!
Domains!Domains!
Domains!
 
Client-Side Packages
Client-Side PackagesClient-Side Packages
Client-Side Packages
 
Creating Truly RESTful APIs
Creating Truly RESTful APIsCreating Truly RESTful APIs
Creating Truly RESTful APIs
 
JavaScript on the Desktop
JavaScript on the DesktopJavaScript on the Desktop
JavaScript on the Desktop
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
Real World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScriptReal World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScript
 
Unit Testing for Great Justice
Unit Testing for Great JusticeUnit Testing for Great Justice
Unit Testing for Great Justice
 
Understanding the Node.js Platform
Understanding the Node.js PlatformUnderstanding the Node.js Platform
Understanding the Node.js Platform
 

Recently uploaded

Getting Started Using the National Research Platform
Getting Started Using the National Research PlatformGetting Started Using the National Research Platform
Getting Started Using the National Research Platform
Larry Smarr
 
STKI Israeli Market Study 2024 final v1
STKI Israeli Market Study 2024 final  v1STKI Israeli Market Study 2024 final  v1
STKI Israeli Market Study 2024 final v1
Dr. Jimmy Schwarzkopf
 
Dev Dives: Mining your data with AI-powered Continuous Discovery
Dev Dives: Mining your data with AI-powered Continuous DiscoveryDev Dives: Mining your data with AI-powered Continuous Discovery
Dev Dives: Mining your data with AI-powered Continuous Discovery
UiPathCommunity
 
Chapter 6 - Test Tools Considerations V4.0
Chapter 6 - Test Tools Considerations V4.0Chapter 6 - Test Tools Considerations V4.0
Chapter 6 - Test Tools Considerations V4.0
Neeraj Kumar Singh
 
APJC Introduction to ThousandEyes Webinar
APJC Introduction to ThousandEyes WebinarAPJC Introduction to ThousandEyes Webinar
APJC Introduction to ThousandEyes Webinar
ThousandEyes
 
ThousandEyes New Product Features and Release Highlights: June 2024
ThousandEyes New Product Features and Release Highlights: June 2024ThousandEyes New Product Features and Release Highlights: June 2024
ThousandEyes New Product Features and Release Highlights: June 2024
ThousandEyes
 
20240702 QFM021 Machine Intelligence Reading List June 2024
20240702 QFM021 Machine Intelligence Reading List June 202420240702 QFM021 Machine Intelligence Reading List June 2024
20240702 QFM021 Machine Intelligence Reading List June 2024
Matthew Sinclair
 
Supplier Sourcing Presentation - Gay De La Cruz.pdf
Supplier Sourcing Presentation - Gay De La Cruz.pdfSupplier Sourcing Presentation - Gay De La Cruz.pdf
Supplier Sourcing Presentation - Gay De La Cruz.pdf
gaydlc2513
 
Database Management Myths for Developers
Database Management Myths for DevelopersDatabase Management Myths for Developers
Database Management Myths for Developers
John Sterrett
 
Coordinate Systems in FME 101 - Webinar Slides
Coordinate Systems in FME 101 - Webinar SlidesCoordinate Systems in FME 101 - Webinar Slides
Coordinate Systems in FME 101 - Webinar Slides
Safe Software
 
CNSCon 2024 Lightning Talk: Don’t Make Me Impersonate My Identity
CNSCon 2024 Lightning Talk: Don’t Make Me Impersonate My IdentityCNSCon 2024 Lightning Talk: Don’t Make Me Impersonate My Identity
CNSCon 2024 Lightning Talk: Don’t Make Me Impersonate My Identity
Cynthia Thomas
 
An Introduction to All Data Enterprise Integration
An Introduction to All Data Enterprise IntegrationAn Introduction to All Data Enterprise Integration
An Introduction to All Data Enterprise Integration
Safe Software
 
Knowledge and Prompt Engineering Part 2 Focus on Prompt Design Approaches
Knowledge and Prompt Engineering Part 2 Focus on Prompt Design ApproachesKnowledge and Prompt Engineering Part 2 Focus on Prompt Design Approaches
Knowledge and Prompt Engineering Part 2 Focus on Prompt Design Approaches
Earley Information Science
 
Building an Agentic RAG locally with Ollama and Milvus
Building an Agentic RAG locally with Ollama and MilvusBuilding an Agentic RAG locally with Ollama and Milvus
Building an Agentic RAG locally with Ollama and Milvus
Zilliz
 
The "Zen" of Python Exemplars - OTel Community Day
The "Zen" of Python Exemplars - OTel Community DayThe "Zen" of Python Exemplars - OTel Community Day
The "Zen" of Python Exemplars - OTel Community Day
Paige Cruz
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
The Digital Insurer
 
Quality Patents: Patents That Stand the Test of Time
Quality Patents: Patents That Stand the Test of TimeQuality Patents: Patents That Stand the Test of Time
Quality Patents: Patents That Stand the Test of Time
Aurora Consulting
 
Transcript: Details of description part II: Describing images in practice - T...
Transcript: Details of description part II: Describing images in practice - T...Transcript: Details of description part II: Describing images in practice - T...
Transcript: Details of description part II: Describing images in practice - T...
BookNet Canada
 
Product Listing Optimization Presentation - Gay De La Cruz.pdf
Product Listing Optimization Presentation - Gay De La Cruz.pdfProduct Listing Optimization Presentation - Gay De La Cruz.pdf
Product Listing Optimization Presentation - Gay De La Cruz.pdf
gaydlc2513
 
Multimodal Retrieval Augmented Generation (RAG) with Milvus
Multimodal Retrieval Augmented Generation (RAG) with MilvusMultimodal Retrieval Augmented Generation (RAG) with Milvus
Multimodal Retrieval Augmented Generation (RAG) with Milvus
Zilliz
 

Recently uploaded (20)

Getting Started Using the National Research Platform
Getting Started Using the National Research PlatformGetting Started Using the National Research Platform
Getting Started Using the National Research Platform
 
STKI Israeli Market Study 2024 final v1
STKI Israeli Market Study 2024 final  v1STKI Israeli Market Study 2024 final  v1
STKI Israeli Market Study 2024 final v1
 
Dev Dives: Mining your data with AI-powered Continuous Discovery
Dev Dives: Mining your data with AI-powered Continuous DiscoveryDev Dives: Mining your data with AI-powered Continuous Discovery
Dev Dives: Mining your data with AI-powered Continuous Discovery
 
Chapter 6 - Test Tools Considerations V4.0
Chapter 6 - Test Tools Considerations V4.0Chapter 6 - Test Tools Considerations V4.0
Chapter 6 - Test Tools Considerations V4.0
 
APJC Introduction to ThousandEyes Webinar
APJC Introduction to ThousandEyes WebinarAPJC Introduction to ThousandEyes Webinar
APJC Introduction to ThousandEyes Webinar
 
ThousandEyes New Product Features and Release Highlights: June 2024
ThousandEyes New Product Features and Release Highlights: June 2024ThousandEyes New Product Features and Release Highlights: June 2024
ThousandEyes New Product Features and Release Highlights: June 2024
 
20240702 QFM021 Machine Intelligence Reading List June 2024
20240702 QFM021 Machine Intelligence Reading List June 202420240702 QFM021 Machine Intelligence Reading List June 2024
20240702 QFM021 Machine Intelligence Reading List June 2024
 
Supplier Sourcing Presentation - Gay De La Cruz.pdf
Supplier Sourcing Presentation - Gay De La Cruz.pdfSupplier Sourcing Presentation - Gay De La Cruz.pdf
Supplier Sourcing Presentation - Gay De La Cruz.pdf
 
Database Management Myths for Developers
Database Management Myths for DevelopersDatabase Management Myths for Developers
Database Management Myths for Developers
 
Coordinate Systems in FME 101 - Webinar Slides
Coordinate Systems in FME 101 - Webinar SlidesCoordinate Systems in FME 101 - Webinar Slides
Coordinate Systems in FME 101 - Webinar Slides
 
CNSCon 2024 Lightning Talk: Don’t Make Me Impersonate My Identity
CNSCon 2024 Lightning Talk: Don’t Make Me Impersonate My IdentityCNSCon 2024 Lightning Talk: Don’t Make Me Impersonate My Identity
CNSCon 2024 Lightning Talk: Don’t Make Me Impersonate My Identity
 
An Introduction to All Data Enterprise Integration
An Introduction to All Data Enterprise IntegrationAn Introduction to All Data Enterprise Integration
An Introduction to All Data Enterprise Integration
 
Knowledge and Prompt Engineering Part 2 Focus on Prompt Design Approaches
Knowledge and Prompt Engineering Part 2 Focus on Prompt Design ApproachesKnowledge and Prompt Engineering Part 2 Focus on Prompt Design Approaches
Knowledge and Prompt Engineering Part 2 Focus on Prompt Design Approaches
 
Building an Agentic RAG locally with Ollama and Milvus
Building an Agentic RAG locally with Ollama and MilvusBuilding an Agentic RAG locally with Ollama and Milvus
Building an Agentic RAG locally with Ollama and Milvus
 
The "Zen" of Python Exemplars - OTel Community Day
The "Zen" of Python Exemplars - OTel Community DayThe "Zen" of Python Exemplars - OTel Community Day
The "Zen" of Python Exemplars - OTel Community Day
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
Quality Patents: Patents That Stand the Test of Time
Quality Patents: Patents That Stand the Test of TimeQuality Patents: Patents That Stand the Test of Time
Quality Patents: Patents That Stand the Test of Time
 
Transcript: Details of description part II: Describing images in practice - T...
Transcript: Details of description part II: Describing images in practice - T...Transcript: Details of description part II: Describing images in practice - T...
Transcript: Details of description part II: Describing images in practice - T...
 
Product Listing Optimization Presentation - Gay De La Cruz.pdf
Product Listing Optimization Presentation - Gay De La Cruz.pdfProduct Listing Optimization Presentation - Gay De La Cruz.pdf
Product Listing Optimization Presentation - Gay De La Cruz.pdf
 
Multimodal Retrieval Augmented Generation (RAG) with Milvus
Multimodal Retrieval Augmented Generation (RAG) with MilvusMultimodal Retrieval Augmented Generation (RAG) with Milvus
Multimodal Retrieval Augmented Generation (RAG) with Milvus
 

Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patterns in JavaScript

  • 1. Callbacks, Promises, and Coroutines (oh my!) Asynchronous Programming Patterns in JavaScript Domenic Denicola http://domenicdenicola.com @domenicdenicola
  • 2. In non-web languages, most of the code we write is synchronous. aka blocking
  • 3. Console.WriteLine("What is your name?"); string name = Console.ReadLine(); Console.WriteLine("Hello, " + name);
  • 4. var fileNames = Directory.EnumerateFiles("C:"); foreach (var fileName in fileNames) { using (var f = File.Open(fileName, FileMode.Open)) { Console.WriteLine(fileName + " " + f.Length); } }
  • 5. using (var client = new WebClient()) { string html = client.DownloadString("http://news.ycombinator.com"); Console.WriteLine(html.Contains("Google")); Console.WriteLine(html.Contains("Microsoft")); Console.WriteLine(html.Contains("Apple")); }
  • 6. Thread.Start BackgroundWorker Control.InvokeRequired This often causes us some pain… … but hey, there’s always threads! Dispatcher.Invoke ThreadPool .AsParallel()
  • 7. Q: What are these threads doing, most of the time? A: waiting
  • 9. In JavaScript, we do things differently.
  • 10. There’s only one thread in JavaScript, so we use that thread to get stuff done.
  • 11. OK, let’s talk about… • The event loop • Callbacks • Promises • Coroutines
  • 13. You’ve seen event loops before:
  • 14. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; while (GetMessage(&msg, NULL, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }
  • 15. this.btnOK.Click += this.btnOK_Click; private void btnOK_Click(object sender, EventArgs e) { // ... }
  • 16. $("#ok-button").click(function () { // ... }); setTimeout(function () { // ... }, 100); $.get("http://example.com", function (result) { // ... });
  • 17. Some event loop subtleties • Yielding • Async’s not sync • Errors • It’s not magic
  • 18. Event Loop Subtleties Yielding console.log("1"); $.get("/echo/2", function (result) { console.log(result); }); console.log("3"); // 1, 3, 2
  • 19. Event Loop Subtleties Async’s not sync var hi = null; $.get("/echo/hi", function (result) { hi = result; }); console.log(hi); // null
  • 20. Event Loop Subtleties Errors console.log("About to get the website..."); $.ajax("http://sometimesdown.example.com", { success: function (result) { console.log(result); }, error: function () { throw new Error("Error getting the website"); } }); console.log("Continuing about my business...");
  • 21. Event Loop Subtleties It’s not magic function fib(n) { return n < 2 ? 1 : fib(n-2) + fib(n-1); } console.log("1"); setTimeout(function () { console.log("2"); }, 100); fib(40); // 1 ... 15 seconds later ... 2 http://teddziuba.com/2011/10/node-js-is-cancer.html
  • 22. The event loop is tricky… but powerful.
  • 24. What we’ve seen so far has been doing asynchronicity through callbacks.
  • 25. Callbacks are OK for simple operations, but force us into continuation passing style.
  • 26. Recurring StackOverflow question: function getY() { var y; $.get("/gety", function (jsonData) { y = jsonData.y; }); return y; } Why doesn’t it work??? var x = 5; var y = getY(); console.log(x + y);
  • 27. After getting our data, we have to do everything else in a continuation:
  • 28. function getY(continueWith) { $.get("/gety", function (jsonData) { continueWith(jsonData.y); }); } var x = 5; getY(function (y) { console.log(x + y); });
  • 29. CPS Headaches • Doing things in sequence is hard • Doing things in parallel is harder • Errors get lost easily
  • 30. CPS Headaches Doing things in sequence is hard $("#button").click(function () { promptUserForTwitterHandle(function (handle) { twitter.getTweetsFor(handle, function (tweets) { ui.show(tweets); }); }); });
  • 31. CPS Headaches Doing things in parallel is harder var tweets, answers, checkins; twitter.getTweetsFor("domenicdenicola", function (result) { tweets = result; somethingFinished(); }); stackOverflow.getAnswersFor("Domenic", function (result) { answers = result; somethingFinished(); }); fourSquare.getCheckinsBy("Domenic", function (result) { checkins = result; somethingFinished(); });
  • 32. CPS Headaches Doing things in parallel is harder var finishedSoFar = 0; function somethingFinished() { if (++finishedSoFar === 3) { ui.show(tweets, answers, checkins); } }
  • 33. CPS Headaches Errors get lost easily function getTotalFileLengths(path, callback) { fs.readdir(path, function (err, fileNames) { var total = 0; var finishedSoFar = 0; function finished() { if (++finishedSoFar === fileNames.length) { callback(total); } } fileNames.forEach(function (fileName) { fs.readFile(fileName, function (err, file) { total += file.length; finished(); }); }); }); }
  • 34. You could write your own library to make this nicer…
  • 35. function parallel(actions, callback) { var results = []; function finished(result) { results.push(result); if (results.length === actions.length) { callback(results); } } actions.forEach(function (action) { action(finished); }); }
  • 36. parallel([ function (cb) { twitter.getTweetsFor("domenicdenicola", cb); }, function (cb) { stackOverflow.getAnswersFor("Domenic", cb); }, function (cb) { fourSquare.getCheckinsFor("Domenic", cb); } ], function (results) { console.log("tweets = ", results[0]); console.log("answers = ", results[1]); console.log("checkins = ", results[2]); });
  • 37. And in fact many people have: https://github.com/joyent/node/wiki/modules#wiki-async-flow
  • 38. The best of these (IMO) are based on an abstraction called “promises”
  • 40. Un-inverts the chain of responsibility: instead of calling a passed callback, return a promise.
  • 41. addWithCallback(a, b, function (result) { assert.equal(result, a + b); }); var promise = addWithPromise(a, b); promise.then(function (result) { assert.equal(result, a + b); });
  • 42. Why promises are awesome • Cleaner method signatures • Uniform return/error semantics • Easy composition • Easy sequential/parallel join • Always async • Exception-style error bubbling
  • 43. Promises are Awesome Cleaner method signatures Uniform return/error semantics $.get( url, [data], [success(data, status, xhr)], [dataType] )
  • 44. Promises are Awesome Cleaner method signatures Uniform return/error semantics $.ajax(url, settings) settings.success(data, status, xhr) settings.error(xhr, status, errorThrown) settings.complete(xhr, status)
  • 45. Promises are Awesome Cleaner method signatures Uniform return/error semantics fs.open( path, flags, [mode], [callback(error, file)] )
  • 46. Promises are Awesome Cleaner method signatures Uniform return/error semantics fs.write( file, buffer, offset, length, position, [callback(error, written, buffer)] )
  • 47. Promises are Awesome Cleaner method signatures Uniform return/error semantics getAsPromise(url, [data], [dataType]).then( function onFulfilled(result) { var data = result.data; var status = result.status; var xhr = result.xhr; }, function onBroken(error) { console.error("Couldn't get", error); } );
  • 48. Promises are Awesome Easy composition function getUser(userName, onSuccess, onError) { $.ajax("/user?" + userName, { success: onSuccess, error: onError }); }
  • 49. Promises are Awesome Easy composition function getUser(userName) { return getAsPromise("/user?" + userName); }
  • 50. Promises are Awesome Easy composition function getFirstName(userName, onSuccess, onError) { $.ajax("/user?" + userName, { success: function successProxy(data) { onSuccess(data.firstName); }, error: onError }); }
  • 51. Promises are Awesome Easy composition function getFirstName(userName) { return getAsPromise("/user?" + userName) .get("firstName"); }
  • 52. Promises are Awesome Easy sequential join $("#button").click(function () { promptUserForTwitterHandle(function (handle) { twitter.getTweetsFor(handle, function (tweets) { ui.show(tweets); }); }); });
  • 53. Promises are Awesome Easy sequential join $("#button").clickPromise() .then(promptUserForTwitterHandle) .then(twitter.getTweetsFor) .then(ui.show);
  • 54. Promises are Awesome Easy parallel join var tweets, answers, checkins; twitter.getTweetsFor("domenicdenicola", function (result) { tweets = result; somethingFinished(); }); stackOverflow.getAnswersFor("Domenic", function (result) { answers = result; somethingFinished(); }); fourSquare.getCheckinsBy("Domenic", function (result) { checkins = result; somethingFinished(); });
  • 55. Promises are Awesome Easy parallel join Q.all([ twitter.getTweetsFor("domenicdenicola"), stackOverflow.getAnswersFor("Domenic"), fourSquare.getCheckinsBy("Domenic") ]).then(function (results) { console.log(results[0], results[1], results[2]); });
  • 56. Promises are Awesome Easy parallel join Q.all([ twitter.getTweetsFor("domenicdenicola"), stackOverflow.getAnswersFor("Domenic"), fourSquare.getCheckinsBy("Domenic") ]).spread(function (tweets, answers, checkins) { console.log(tweets, answers, checkins); });
  • 57. Promises are Awesome Always async function getUser(userName, onSuccess, onError) { if (cache.has(userName)) { onSuccess(cache.get(userName)); } else { $.ajax("/user?" + userName, { success: onSuccess, error: onError }); } }
  • 58. Promises are Awesome Always async console.log("1"); getUser("ddenicola", function (user) { console.log(user.firstName); }); console.log("2"); // 1, 2, Domenic
  • 59. Promises are Awesome Always async console.log("1"); getUser("ddenicola", function (user) { console.log(user.firstName); }); console.log("2"); // 1, Domenic, 2
  • 60. Promises are Awesome Always async function getUser(userName) { if (cache.has(userName)) { return Q.ref(cache.get(userName)); } else { return getWithPromise("/user?" + userName); } }
  • 61. Promises are Awesome Always async console.log("1"); getUser("ddenicola").then(function (user) { console.log(user.firstName); }); console.log("2"); // 1, 2, Domenic (every time)
  • 62. Promises are Awesome Exception-style error bubbling getUser("Domenic", function (user) { getBestFriend(user, function (friend) { ui.showBestFriend(friend); }); });
  • 63. Promises are Awesome Exception-style error bubbling getUser("Domenic", function (err, user) { if (err) { ui.error(err); } else { getBestFriend(user, function (err, friend) { if (err) { ui.error(err); } else { ui.showBestFriend(friend); } }); } });
  • 64. Promises are Awesome Exception-style error bubbling getUser("Domenic") .then(getBestFriend, ui.error) .then(ui.showBestFriend, ui.error);
  • 65. Promises are Awesome Exception-style error bubbling getUser("Domenic") .then(getBestFriend) .then(ui.showBestFriend, ui.error);
  • 66. Promises are Awesome Exception-style error bubbling ui.startSpinner(); getUser("Domenic") .then(getBestFriend) .then( function (friend) { ui.showBestFriend(friend); ui.stopSpinner(); }, function (error) { ui.error(error); ui.stopSpinner(); } );
  • 67. Promises are Awesome Exception-style error bubbling ui.startSpinner(); getUser("Domenic") .then(getBestFriend) .then(ui.showBestFriend, ui.error) .fin(ui.stopSpinner);
  • 68. Promises are Awesome Exception-style error bubbling function getBestFriendAndDontGiveUp(user) { return getUser(user).then( getBestFriend, function (error) { if (error instanceof TemporaryNetworkError) { console.log("Retrying after error", error); return getBestFriendAndDontGiveUp(user); } throw error; }); }
  • 69. Sounds great. How do I get in on this action?
  • 70. Use Q • By Kris Kowal, @kriskowal • https://github.com/kriskowal/q • Can consume promises from jQuery etc. • Implements various CommonJS standards
  • 71. If you’re already using jQuery’s promises, switch to Q: https://github.com/kriskowal/q/wiki/jQuery
  • 73. Creating promises with Q Fulfilling promises // We have: setTimeout(doSomething, 1000); // We want: delay(1000).then(doSomething);
  • 74. Creating promises with Q Fulfilling promises function delay(ms) { var deferred = Q.defer(); setTimeout(deferred.resolve, ms); return deferred.promise; } delay(1000).then(doSomething);
  • 75. Creating promises with Q Breaking promises function getWithTimeout(url, ms, onSuccess, onError) { var isTimedOut = false, isHttpErrored = false; setTimeout(function () { if (!isHttpErrored) { isTimedOut = true; onError(new Error("timed out")); } }, ms); $.ajax(url, { success: function (result) { if (!isTimedOut) { onSuccess(result); } }, error: function (xhr, status, error) { if (!isTimedOut) { isHttpErrored = true; onError(error); } } }); }
  • 76. Creating promises with Q Breaking promises function getWithTimeout(url, ms) { var deferred = Q.defer(); setTimeout(function () { deferred.reject(new Error("timed out")); }, ms); $.ajax(url, { success: deferred.resolve, error: deferred.reject }); return deferred.promise; }
  • 77. Creating promises with Q Building abstractions function timeout(promise, ms) { var deferred = Q.defer(); promise.then(deferred.resolve, deferred.reject); setTimeout(function () { deferred.reject(new Error("timed out")); }, ms); return deferred.promise; } function getWithTimeout(url, ms) { return timeout(getAsPromise(url), ms); }
  • 79. They clean up our method signatures. They’re composable, they’re joinable, and they’re dependably async. They unify various callback conventions into something very much like return values and exceptions.
  • 80. But… we still have to write in CPS.
  • 82. “Coroutines are computer program components that generalize subroutines to allow multiple entry points for suspending and resuming execution at certain locations.” http://en.wikipedia.org/wiki/Coroutine
  • 83. WTF!?
  • 84. Nice: var xP = getX(); var yP = getY(); var zP = getZ(); Q.all([xP, yP, zP]).spread(function (x, y, z) { console.log(x + y + z); });
  • 85. Nicer: var [x, y, z] = await Q.all([getX(), getY(), getZ()]); console.log(x + y + z);
  • 86. Nice: $("#button").clickPromise() .then(promptUserForTwitterHandle) .then(twitter.getTweetsFor) .then(ui.show);
  • 87. Nicer: await $("#button").clickPromise(); var handle = await promptUserForTwitterHandle(); var tweets = await twitter.getTweetsFor(handle); ui.show(tweets);
  • 88. Q: Can’t the compiler do this for me? A: yes… if you are willing to introduce a compiler.
  • 89. Several options, none perfect • Kaffeine: http://weepy.github.com/kaffeine/ • Traceur: http://tinyurl.com/traceur-js • TameJS: http://tamejs.org/ • Node fork: http://tinyurl.com/node-async
  • 90. Q: OK well… can’t the interpreter do this for me? A: yes… if you’re willing to wait for the next version of JS.
  • 91. The next version of JavaScript (“ECMAScript Harmony”) has a limited form of coroutines that can be twisted to do something like what we want.
  • 92. ECMAScript Harmony generators function* fibonacci() { var [prev, curr] = [0, 1]; for (;;) { [prev, curr] = [curr, prev + curr]; yield curr; } } for (n of fibonnaci()) { console.log(n); } http://wiki.ecmascript.org/doku.php?id=harmony:generators
  • 93. ECMAScript Harmony generators var eventualAdd = Q.async(function* (pA, pB) { var a = yield pA; var b = yield pB; return a + b; }); https://github.com/kriskowal/q/tree/master/examples/async-generators
  • 94. ECMAScript Harmony generators // Can only use yield as we want to within // Q.async'ed generator functions Q.async(function* () { // Talk to the server to get one and two. var three = yield eventualAdd(getOne(), getTwo()); assert.equal(three, 3); })(); https://groups.google.com/d/topic/q-continuum/7PWKbgeFA48/discussion
  • 95. ECMAScript Harmony generators // Given promise-returning delay(ms) as before: var animateAsync = Q.async(function* (el) { for (var i = 0; i < 100; ++i) { element.style.left = i; yield delay(20); } }); http://wiki.ecmascript.org/doku.php?id=strawman:async_functions
  • 96. ECMAScript Harmony generators Q.async(function* () { var el = document.getElementById("my-element"); yield animateAsync(el); console.log("it's done animating"); })(); https://groups.google.com/d/topic/q-continuum/7PWKbgeFA48/discussion
  • 97. So coroutines are a bit of a mess, but we’ll see how things shape up.
  • 98. Recap • Async is here to stay • But you don’t have to dive into callback hell • Use promises • Use Q • Maybe use coroutines if you’re feeling brave

Editor's Notes

  1. Decouples the action from the subsequent use of the result.