exercises

Log | Files | Refs | README

coroutines_promises_and_futures.js (1887B)


      1 // Promises in JavaScript and futures and in Rust are two different implementations that are based on the same idea.
      2 //
      3 // Promises are one way to deal with the complexity that comes with
      4 // a callback-based approach.
      5 
      6 
      7 // Instead of:
      8 setTimer(200, () => {
      9   setTimer(100, () => {
     10     setTimer(50, () => {
     11       console.log("I'm the last one");
     12     });
     13   });
     14 });
     15 
     16 // We can do:
     17 //
     18 // You see, promises return a State Machine that can be in one of
     19 // three states: Pending, Fullfilled, or Rejected.
     20 function timer(ms) {
     21   return new Promise((resolve) => setTimeout(resolve, ms));
     22 }
     23 // This is referred to as the continuation-passing style.
     24 // Each subtask calls a new one once it's finished.
     25 timer(200)
     26 .then(() => timer(100))
     27 .then(() => timer(50))
     28 .then(() => console.log("I'm the last one"));
     29 
     30 // Coroutines and async/await
     31 //
     32 // - Async: the compiler rewrites what looks like a normal function
     33 // call into a `future` (in Rust) or a `promise` (in JavaScript).
     34 // 
     35 // - Await, yields control to the runtime scheduler, and the task
     36 // is suspended until the future/promise you're awaiting
     37 // has finished.
     38 //
     39 // This way, we can write programs that handle concurrent operations
     40 // in almost the same way we write our normal sequential programs.
     41 //
     42 // You can consider the run function as a pausable task consisting
     43 // of several sub-tasks. On each "await" point, it yields control to the scheduler (in this case, it's the JavaScript event loop).
     44 //
     45 // Once one of the sub-tasks changes state to either `fullfilled` or
     46 // `rejected`, the task is scheduled to continue to the next step.
     47 async function run() {
     48   await timer(200);
     49   await timer(100);
     50   await timer(50);
     51   console.log("I'm the last one");
     52 }
     53 
     54 // In Rust, you can see the same transformation happening with the
     55 // function signature:
     56 //
     57 // From:
     58 // async fn run() -> () {...}
     59 //
     60 // To:
     61 // Fn run() -> impl Future<Output = ()>