3

Can you explain to a beginner the differences between "promises", "async", and "callbacks". How do these terms relate to one another? Are these the same thing? Different things? When do I use which?

Michael Aaron Safyan
  • 93,612
  • 16
  • 138
  • 200
Amanda Merla
  • 157
  • 1
  • 2
  • 6
  • 2
    Which one you should use is opinion based. The other questions have already been asked individually: http://stackoverflow.com/questions/824234/what-is-a-callback-function - http://stackoverflow.com/questions/6801283/what-are-the-differences-between-deferred-promise-and-future-in-javascript . As for the async library vs Promises, promises are _much_ more powerful and composable but that's again _my_ opinion. – Benjamin Gruenbaum Aug 05 '14 at 08:10
  • 2
    In my __opinion__ while you are learning you should first learn the JavaScript concurrency model (that is, everything is synchronous except for "host functions" given to you by the API). How [cps works in JavaScript](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call) and more generally how functions accept function parameters and only finally - how promise work (they're not magic :)). Only when you learn those things I'd use promises which in my _opinion_ are a much better alternative to callbacks since they do error handling better and compose better. – Benjamin Gruenbaum Aug 05 '14 at 08:12
  • 1
    This is a valid question and not opinion based. The terms are highly interrelated, and a clarification of the different terms would be appropriate. Please reopen. – Michael Aaron Safyan Aug 05 '14 at 08:15
  • 1
    @MichaelAaronSafyan before the edit it was opinion based, after the edit it's a pretty close duplicate of http://stackoverflow.com/questions/4296505/understanding-promises-in-node-js . – Benjamin Gruenbaum Aug 05 '14 at 08:19
  • 1
    From my experience most things can be achieved by the use of promises, plus it gives a clear understanding of the flow. In the cons of using promises are, projects that use promises tend to use them everywhere, which sometimes leads to needs of wrapping modules that are not using them. Async can easily be combined with heavily use of CBs, so in cases of long flows, it can give a better structure. But as @Benjamin Gruenbaum mentioned, you shall first understand the JS concurrency model, before going any further. – Evan P Aug 05 '14 at 08:20
  • 1
    @MichaelAaronSafyan Although to be fair, I think [this Q&A](http://stackoverflow.com/questions/22539815/arent-promises-just-callbacks) is closer to what OP is interested in (how are promises different from callbacks). – Benjamin Gruenbaum Aug 05 '14 at 08:21
  • @Evalon A lot of things _can't_ be achieved by the use of promises. They are not event emitters nor they are streams. A promise represents the a single operation and it only resolves once. They are useful and awesome but they're definitely not a concurrency silver bullet. – Benjamin Gruenbaum Aug 05 '14 at 08:22
  • Before the edit, the focus didn't seem particularly opionion-based to me. In any event, the frustration that it creates both for the person asking the question and for the person who writes three paragraphs of answer really makes closing a terrible procedure. – Michael Aaron Safyan Aug 05 '14 at 08:23
  • @MichaelAaronSafyan I completely agree (and this has been discussed on meta) and I would love for you to post your answer on it on [this duplicate](http://stackoverflow.com/questions/22539815/arent-promises-just-callbacks). – Benjamin Gruenbaum Aug 05 '14 at 08:24
  • My answer was tailored to the way the question was phrased, so I can't just repost my answer. For example, the other question doesn't ask about the relationship of "async" and "callback" (and, in fact, presupposes an understanding of what "callbacks" are), whereas this question demonstrates a lack of understanding of those terms. – Michael Aaron Safyan Aug 05 '14 at 08:25
  • @Benjamin Gruenbaum That's true, but Events, promises and Streams are totally different things. I don't understand your confusion. You can combine them, or Wrap them with promises but such discussion is out of the context of this discussion. Also this brings questions, if this is a good practise after all. – Evan P Aug 05 '14 at 08:26
  • @MichaelAaronSafyan well, if you believe you can answer this question well I'll give you the benefit of the doubt and vote to reopen it and ask friends to too - given the edit, after all I don't want to stand in the way of someone who wants to contribute. Good luck. – Benjamin Gruenbaum Aug 05 '14 at 08:32
  • @MichaelAaronSafyan done. Good luck :) – Benjamin Gruenbaum Aug 05 '14 at 08:37
  • I think this should exist, once a *decent* attempt at a canonical answer has been provided, and it should be protected after that. – Jimbo Aug 05 '14 at 08:37

1 Answers1

7

Async is the general design pattern of starting a computation and providing a function or registering a handler that will eventually get called with the result of the computation when it has completed (as opposed to blocking and waiting for the computation to complete before starting additional work). Without async, starting multiple computations simultaneously requires the use of threads.

A "callback" refers to the function that you provide to an async computation that will get invoked when that computation completes. It is called a "callback" because it gets called by the async function, and in getting called, it returns the flow of control back into code that you have control over.

A "Promise" is a specific JavaScript prototype and associated framework that brings consistency to code that is written in an asynchronous style. A Promise represents an async computation that may or may not have completed (successfully or unsuccessfully) and provides a means of operating on the result or handling errors regardless of the state of completion of the asynchronous computation. The Promise API also provides utilities for combining the outputs of multiple asynchronous computations (such as waiting for one of or all of a set of asynchronous computations to complete before the next calculation).

To give a simple example without Promises:

var addThen = function(a, b, handler) {
  var result = a + b;
  handler(result);
};

// ...
addThen(2, 3, console.log);  // prints 5
// ...

And the equivalent with Promise:

var add = function(a, b) {
  return Promise.resolve(a + b);
};

// ...
add(2, 3).then(console.log); // prints 5
// ...

Async code can be written both with and without Promises, but the primary advantage of using Promise is consistency (e.g. where in the argument list the success callback and failure callbacks go, whether a failure callback is supported or not, etc.) and support libraries that can combine them together.

Michael Aaron Safyan
  • 93,612
  • 16
  • 138
  • 200
  • This is a worthwhile read on promises: http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/ – Benjamin Gruenbaum Aug 05 '14 at 08:47
  • A callback doesn't have to be async, it's about inversion of control - it can act as a command or as a strategy for computation. For example in `[1, 2, 3, 4, 5, 0, 4].map(Boolean)` nothing asynchronous happen yet the function `Boolean` function function is passed as a callback. It's really about inversion of control. Promises are not a JavaScript prototype nor are they a framework, they are a concept pioneered by people like Mark Miller and Barbara Liskov before JavaScript was even a thing. – Benjamin Gruenbaum Aug 05 '14 at 08:51
  • Adding, I would not call "Async" a design pattern - the pattern is [CPS](http://en.wikipedia.org/wiki/Continuation-passing_style). Moreover, you don't need to have threads to do concurrency without it (a good counterexample is coroutines). JavaScript concurrency through callbacks is in itself just concurrency and the fact multiple computations happen simultaneously is because of host objects and not JavaScript (which doesn't have a notion of concurrency at all until ES6). – Benjamin Gruenbaum Aug 05 '14 at 08:52
  • All of those are excellent comments. Like "parallel" vs "concurrent", it really depends on how precise we are trying to be with language and if the focus is on how the code is structured or on the order in which it is executed. You're right, though, that async really is assuming that there is some delay (e.g. due to the network), whereas the dummy examples I provided provide results immediately. CPS can be used for immediate results but it is more useful and popular in the context of async. – Michael Aaron Safyan Aug 05 '14 at 09:03
  • There is a specific implementation of Promise in browsers now, though you are right that there were various incarnations of it before that. Given the tags "JavaScript" and "Node.js", I think it is reasonable to assume that this is what the OP had in mind as opposed to the general pattern of Promise/Future/whatever. I should also point out that coroutines are basically light-weight userspace threads, but they're basically the same thing. For the OP's level of knowledge, I don't think the distinction is helpful. – Michael Aaron Safyan Aug 05 '14 at 09:08
  • I wouldn't, as well, narrow the term of "callback" as only a way of providing asynchronous flow. I think the best explanation and most safe is to explain what a First Class function is. http://en.wikipedia.org/wiki/First-class_function – Evan P Aug 05 '14 at 13:01
  • This is a good opening gambit but, for me, all three definitions fall short of encyclopaedia entries. Needs a lot more work. – Roamer-1888 Aug 06 '14 at 16:42