-
Notifications
You must be signed in to change notification settings - Fork 84
PromisesVsTasks
Promise
is a well-defined built-in object that makes it easy, among other things, to chain synchronous or asynchronous operations.
Task
is an object defined in trace_viewer/base that can be used to chain synchronous operations.
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.
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.
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. Creating a promise is typically a lightweight operation that returns immediately.
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()
.
Chaining operations is handled slightly differently. Compare:
taskA.after(taskB.after(taskC));
promiseA.then(functionReturningPromiseB).then(functionReturningPromiseC);
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.
The most important difference lies in the way tasks and promises are executed. When calling run()
on a task, the first task is executed synchronously following which the control is given back to the caller. The caller then has the option to run the next task or yield. A promise, on the other hand, is scheduled for execution as soon as it is created and the caller must use then()
to be notified of the operation's completion.
Task.RunWhenIdle
is another API call that is not available on promises. It will consume the task queue asynchronously in a gradual way, 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
.
There are a number of other small API difference which are not as important as the ones above.
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
.
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.