Skip to content
This repository has been archived by the owner on Jul 27, 2022. It is now read-only.

PromisesVsTasks

Philippe Beaudoin edited this page Jun 9, 2015 · 10 revisions

Promises vs Tasks

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.

Semantic differences

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().

Differences in API

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.

What should you use?

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.

Future works

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.

Clone this wiki locally