Home | History | Annotate | Download | only in docs
      1 # Promises vs Tasks
      2 
      3 `Promise` is a well-defined [built-in object](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise) that makes it easy, among other things, to chain synchronous or asynchronous operations.
      4 
      5 `Task` is an object defined in trace_viewer/base that can be used to chain synchronous operations.
      6 
      7 Since both tasks and promises allow chaining operations it's easy to confuse them. The goal of this page is to clarify how the classes differ and when to use either.
      8 
      9 ## Semantic differences
     10 
     11 A first important difference is that tasks cannot be used with asynchronous operations. In a `Promise`, you can chain an asynchronous operation by calling `then(functionReturningAPromise)`. On the other hand, if you create a task from `functionReturningAPromise` and call `after()` on it, then the subsequent task will execute before the promise is resolved.
     12 
     13 Another difference is that it's possible to run a task in a synchronous way. Calling `run()` on a task will block until the first task in the chain is completed. This is made possible by the fact that all operations in the task queue are synchronous. Compare this to `Promise` which doesn't have a `run` method and for which execution is scheduled as soon as the promise is created.
     14 
     15 Finally, where tasks allow a queue of dependent operations, promises are more flexible and allow creating a more complex dependency graph between operations via `then()`, `Promise.all()` and `Promise.race()`.
     16 
     17 ## Differences in API
     18 
     19 Chaining operations is similar:
     20 
     21     taskA.after(taskB).after(taskC);
     22     promiseA.then(functionReturningPromiseB).then(functionReturningPromiseC);
     23 
     24 An important difference, though is a task can only have one `after()` task. Trying to do `taskA.after(taskB); taskA.after(taskC);` will result in a runtime error. Promises have no such limitations.
     25 
     26 In addition to `after()`, tasks expose the method `subtask()` that makes it possible to insert tasks in the execution chain, even as the operations in the chain are being executed. Promises do not directly support this feature.
     27 
     28 Tasks have a `run()` method to synchronously execute the next operation in the queue. Promises have no such thing, and getting control back once a promise has executed requires the use of `then()`.
     29 
     30 `Task.RunWhenIdle` is another API call that is not available on promises. It schedule the task queue to be gradually consumed, tying task execution to `requestAnimationFrame` in a way that makes sure not to bust the time budget for a frame. Given its asynchronous nature `RunWhenIdle` returns a `Promise`.
     31 
     32 Note that there are a number of other minor API differences that are omitted here.
     33 
     34 ## What should you use?
     35 
     36 If some of the operations you want to chain are asynchronous then you don't have a choice and must use `Promise`. If you want to chain only synchronous operations, then `Task` may be the right choice for you, especially if you plan on executing your operations when the application is idle, in which case you'll want to benefit from `RunWhenIdle`.
     37 
     38 ## Future works
     39 
     40 It's sad that the nature of tasks makes it impossible to use `RunWhenIdle` with an asynchronous operation. It might be interesting to figure out whether it's possible to build a `RunWhenIdle` on top of promises. Also, if the `after()` and `subtask()` API of tasks make the code simpler in some instances it may be interesting to try to reproduce it on top of promises. Given these improvements to `Promise` it may be possible to eventually remove `Task` entirely.
     41