Skip to content

Concepts: differences between Promise, Deferred, and FastDeferred

Eugene Lazutkin edited this page Mar 6, 2016 · 10 revisions

At the moment of this writing (2016), promises prove to be an invaluable tool to handle asynchronous operations. Yet they reveal numerous practical problems in this field:

  • Standard promises defined by ES6, yet not implemented across all popular platforms:
    • Only latest versions of node.js support promises.
    • Most browsers do not support promises yet.
  • The promise definition requires running callbacks and errbacks in a separate time slice.
    • Browsers do not support time slices directly (safe for setImmediate() on IE10 and up). Such functionality has to be approximated with time delays, which introduce ... time delays that can be compounded in certain situations affecting responsiveness. Following techniques can be used:
      • setTimeout()
      • postMessage()
      • requestAnimationFrame()
    • Many time delays in reality completely indeterminate because their actual delay depends on visibility of a web application window, rendering tasks at hand, complexity of CSS, and other hard-to-estimate factors.
  • It is extremely difficult to debug asynchronous problems partly because delaying code to the next time slice removes a valuable context: a call stack. While we know that something is wrong with a state, we don't know how we arrived to this state.
  • It can be difficult to debug code when even unintended exceptions are converted to rejected states. An exception is appeared to be "swallowed", manifesting itself in some unexpected places.
    • Converting exceptions to rejected states require a try/catch pair, which is known to prevent JIT on some platforms, e.g., V8 of node.js and Chrome.
  • Missing functionality to support asynchronous functions:
    • Our asynchronous code may stop waiting for an asynchronous operation to complete. Use case: user decided to switch to a different page without waiting for a lengthy I/O to show all items on this page, user don't want to finish long processing delegated to a server, and so on. We should be able to cancel such operation, or at the very least to communicate that we are not interested in the result (other clients of the same promise may be still interested in it).
    • Long asynchronous operations are required to provide a feedback on their progress, so user can make informed decisions on waiting vs. canceling. Some experts advise to use a different mechanism for that, e.g., event streams, but doing so has two major drawbacks:
      • We have to recreate a topology already created with promises.
      • It doubles API, and doubles the code. Shipping more code to browser, especially on mobile networks, effects the overall performance negatively, especially clients with cold cache.
      • It may introduce a close coupling between a producer and a consumer of progress events.