276

I’ve been seeing code that looks like:

myObj.doSome("task").then(function(env) {    // logic});

Where does then() come from?

12 Answers 12

350
2

The traditional way to deal with asynchronous calls in JavaScript has been with callbacks.Say we had to make three calls to the server, one after the other, to set up ourapplication. With callbacks, the code might look something like the following (assuminga xhrGET function to make the server call):

// Fetch some server configuration    xhrGET('/api/server-config', function(config) {        // Fetch the user information, if he's logged in        xhrGET('/api/' + config.USER_END_POINT, function(user) {            // Fetch the items for the user            xhrGET('/api/' + user.id + '/items', function(items) {                // Actually display the items here            });        });    });

In this example, we first fetch the server configuration. Then based on that, we fetchinformation about the current user, and then finally get the list of items for the currentuser. Each xhrGET call takes a callback function that is executed when the serverresponds.

Now of course the more levels of nesting we have, the harder the code is to read, debug,maintain, upgrade, and basically work with. This is generally known as callback hell.Also, if we needed to handle errors, we need to possibly pass in another function to eachxhrGET call to tell it what it needs to do in case of an error. If we wanted to have just onecommon error handler, that is not possible.

The Promise API was designed to solve this nesting problem and the problem of error handling.

The Promise API proposes the following:

  1. Each asynchronous task will return a promise object.
  2. Each promise object will have a then function that can take two arguments, a successhandler and an error handler.
  3. The success or the error handler in the then function will be called only once, afterthe asynchronous task finishes.
  4. The then function will also return a promise, to allow chaining multiple calls.
  5. Each handler (success or error) can return a value, which will be passed to the next function as an argument, in the chain of promises.
  6. If a handler returns a promise (makes another asynchronous request), then the nexthandler (success or error) will be called only after that request is finished.

So the previous example code might translate to something like the following, usingpromises and the $http service(in AngularJs):

$http.get('/api/server-config').then(    function(configResponse) {        return $http.get('/api/' + configResponse.data.USER_END_POINT);    }).then(    function(userResponse) {        return $http.get('/api/' + userResponse.data.id + '/items');    }).then(    function(itemResponse) {        // Display items here    },     function(error) {        // Common error handling    });

Propagating Success and Error

Chaining promises is a very powerful technique that allows us to accomplish a lot offunctionality, like having a service make a server call, do some postprocessing of thedata, and then return the processed data to the controller. But when we work withpromise chains, there are a few things we need to keep in mind.

Consider the following hypothetical promise chain with three promises, P1, P2, and P3.Each promise has a success handler and an error handler, so S1 and E1 for P1, S2 andE2 for P2, and S3 and E3 for P3:

xhrCall()  .then(S1, E1) //P1  .then(S2, E2) //P2  .then(S3, E3) //P3

In the normal flow of things, where there are no errors, the application would flowthrough S1, S2, and finally, S3. But in real life, things are never that smooth. P1 mightencounter an error, or P2 might encounter an error, triggering E1 or E2.

Consider the following cases:

• We receive a successful response from the server in P1, but the data returned is notcorrect, or there is no data available on the server (think empty array). In such acase, for the next promise P2, it should trigger the error handler E2.

• We receive an error for promise P2, triggering E2. But inside the handler, we havedata from the cache, ensuring that the application can load as normal. In that case,we might want to ensure that after E2, S3 is called.

So each time we write a success or an error handler, we need to make a call—given ourcurrent function, is this promise a success or a failure for the next handler in the promisechain?

If we want to trigger the success handler for the next promise in the chain, we can justreturn a value from the success or the error handler

If, on the other hand, we want to trigger the error handler for the next promise in thechain, we can do that using a deferred object and calling its reject() method

Now What is deferred object?

Deferred objects in jQuery represents a unit of work that will be completed later, typically asynchronously. Once the unit of work completes, the deferred object can be set to resolved or failed.

A deferred object contains a promise object. Via the promise object you can specify what is to happen when the unit of work completes. You do so by setting callback functions on the promise object.

Deferred objects in Jquery : https://api.jquery.com/jquery.deferred/

Deferred objects in AngularJs : https://docs.angularjs.org/api/ng/service/$q

share | improve this answer | |
  • 3
    Very well written. This has helped me really nail down promises. – Ju66ernaut Dec 30 '16 at 21:42
  • Is the error handler, the second parameter, always optional? – 1.21 gigawatts Jan 28 '18 at 0:52
  • This is by far the best answer I have seen so far! – Imam Bux Apr 4 '18 at 10:37
78
0

then() function is related to "Javascript promises" that are used in some libraries or frameworks like jQuery or AngularJS.

A promise is a pattern for handling asynchronous operations. The promise allows you to call a method called "then" that lets you specify the function(s) to use as the callbacks.

For more information see: http://wildermuth.com/2013/8/3/JavaScript_Promises

And for Angular promises: http://liamkaufman.com/blog/2013/09/09/using-angularjs-promises/

share | improve this answer | |
  • 4
    so it's like a callback that executes when task is done? How is it different – Muhammad Umer Mar 23 '14 at 0:19
  • 3
    the JavaScript Promises in the other comment says: A promise can only succeed or fail once, and If a promise has succeeded or failed and you later add a success/failure callback, the correct callback will be called – Xiao Jan 1 '15 at 17:09
  • Also, the Promise nuggets explains how to use promise and what would be done with callback – Xiao Jan 1 '15 at 17:42
  • On the first page, there are chunks of code missing (big white blanks). Most of the people will think of inspecting element and find the fiddle's URLs underneath. This message is for the rest - fiddles still work ;) – DanteTheSmith Jun 5 '17 at 10:12
  • 1
    @MuhammadUmer : read this stackoverflow.com/a/31453579/1350476 (answer by Sid) – SharpCoder Aug 6 '17 at 15:49
32
0

To my knowledge, there isn't a built-in then() method in javascript (at the time of this writing).

It appears that whatever it is that doSome("task") is returning has a method called then.

If you log the return result of doSome() to the console, you should be able to see the properties of what was returned.

console.log( myObj.doSome("task") ); // Expand the returned object in the                                     //   console to see its properties.

UPDATE (As of ECMAScript6) :-

The .then() function has been included to pure javascript.

From the Mozilla documentation here,

The then() method returns a Promise. It takes two arguments: callback functions for the success and failure cases of the Promise.

The Promise object, in turn, is defined as

The Promise object is used for deferred and asynchronous computations. A Promise represents an operation that hasn't completed yet, but is expected in the future.

That is, the Promise acts as a placeholder for a value that is not yet computed, but shall be resolved in the future. And the .then() function is used to associate the functions to be invoked on the Promise when it is resolved - either as a success or a failure.

share | improve this answer | |
  • 12
    There wasn't a built-in .then back then, but native promises are coming now in ES6: html5rocks.com/en/tutorials/es6/promises – janfoeh Dec 17 '13 at 10:25
  • thanks for this answer, I was expecting some cool promise callback but it turned out to be an actual function called 'then' that was returned. – spartikus May 2 '16 at 23:37
15
0

Here is a thing I made for myself to clear out how things work. I guess others too can find this concrete example useful:

doit().then(function() { log('Now finally done!') });log('---- But notice where this ends up!');// For pedagogical reasons I originally wrote the following doit()-function so that // it was clear that it is a promise. That way wasn't really a normal way to do // it though, and therefore Slikts edited my answer. I therefore now want to remind // you here that the return value of the following function is a promise, because // it is an async function (every async function returns a promise). async function doit() {  log('Calling someTimeConsumingThing');  await someTimeConsumingThing();  log('Ready with someTimeConsumingThing');}function someTimeConsumingThing() {  return new Promise(function(resolve,reject) {    setTimeout(resolve, 2000);  })}function log(txt) {  document.getElementById('msg').innerHTML += txt + '<br>'}
<div id='msg'></div>
share | improve this answer | |
5
0

Here is a small JS_Fiddle.

then is a method callback stack which is available after a promise is resolved it is part of library like jQuery but now it is available in native JavaScript and below is the detail explanation how it works

You can do a Promise in native JavaScript : just like there are promises in jQuery, Every promise can be stacked and then can be called with Resolve and Reject callbacks, This is how you can chain asynchronous calls.

I forked and Edited from MSDN Docs on Battery charging status..

What this does is try to find out if user laptop or device is charging battery. then is called and you can do your work post success.

navigator    .getBattery()    .then(function(battery) {       var charging = battery.charging;       alert(charging);    })    .then(function(){alert("YeoMan : SINGH is King !!");});

Another es6 Example

function fetchAsync (url, timeout, onData, onError) {    …}let fetchPromised = (url, timeout) => {    return new Promise((resolve, reject) => {        fetchAsync(url, timeout, resolve, reject)    })}Promise.all([    fetchPromised("http://backend/foo.txt", 500),    fetchPromised("http://backend/bar.txt", 500),    fetchPromised("http://backend/baz.txt", 500)]).then((data) => {    let [ foo, bar, baz ] = data    console.log(`success: foo=${foo} bar=${bar} baz=${baz}`)}, (err) => {    console.log(`error: ${err}`)})

Definition :: then is a method used to solve Asynchronous callbacks

this is introduced in ES6

Please find the proper documentation here Es6 Promises

share | improve this answer | |
  • Your answer does not actually answer the question. It only provides an example of the API usage without explaining where then comes from and how it works. You should improve your answer to provide those details. – Didier L Oct 8 '16 at 15:02
  • @TarandeepSingh - in first then statement where you alert the battery status no promise object is returned. Then what is the use of second then – Mohit Jain Feb 5 '18 at 7:50
  • @MohitJain It showcase you can do multiple callbacks even if you do not have any new promise. Since, the multiple calls could also be done with Promise.all. – Tarandeep Singh May 3 '18 at 12:39
  • WTH do you mean by "method callback stack"? – Bergi Nov 17 '19 at 15:34
4
0

I suspect doSome returns this, which is myObj, which also has a then method. Standard method chaining...

if doSome is not returning this, being the object on which doSome was executed, rest assured it is returning some object with a then method...

as @patrick points out, there is no then() for standard js

share | improve this answer | |
  • 1
    I suspect doSome returns this - nothing enforces/justifies such suspitions – Salathiel Genèse Dec 31 '18 at 15:52
2
0

.then returns a promise in async function.

Good Example would be:

var doSome = new Promise(function(resolve, reject){    resolve('I am doing something');});doSome.then(function(value){    console.log(value);});

To add another logic to it, you can also add the reject('I am the rejected param') call the function and console.log it.

share | improve this answer | |
1
0

doSome("task")must be returning a promise object , and that promise always have a then function .So your code is just like this

promise.then(function(env) {    // logic}); 

and you know this is just an ordinary call to member function .

share | improve this answer | |
0
0

In this case then() is a class method of the object returned by doSome() method.

share | improve this answer | |
0
0

The ".then()" function is wideley used for promised objects in Asynchoronus programming For Windows 8 Store Apps.As far as i understood it works some way like a callback.

Find Details in this Documentantionhttp://msdn.microsoft.com/en-us/library/windows/apps/hh700330.aspx

Of Cause it could also be the name for any other defined function.

share | improve this answer | |
0
0

Another example:

new Promise(function(ok) {   ok(       /* myFunc1(param1, param2, ..) */   )}).then(function(){     /* myFunc1 succeed */     /* Launch something else */     /* console.log(whateverparam1) */     /* myFunc2(whateverparam1, otherparam, ..) */}).then(function(){     /* myFunc2 succeed */     /* Launch something else */     /* myFunc3(whatever38, ..) */})

The same logic using arrow functions shorthand:

new Promise((ok) =>   ok(       /* myFunc1(param1, param2, ..) */)).then(() =>     /* myFunc1 succeed */     /* Launch something else */     /* Only ONE call or statment can be made inside arrow functions */     /* For example, using console.log here will break everything */     /* myFunc2(whateverparam1, otherparam, ..) */).then(() =>     /* myFunc2 succeed */     /* Launch something else */     /* Only ONE call or statment can be made inside arrow functions */     /* For example, using console.log here will break everything */     /* myFunc3(whatever38, ..) */)
share | improve this answer | |
-5
0

I am about 8 years late, well...anyways, I don't really know what then() does but maybe MDN might have an answer. Actually, I might actually understand it a little more.

This will show you all the information (hopefully), you need. Unless someone already posted this link.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

The format is promise.prototype.then()The promise and prototype are kind of like variables but not like variables in javascript, I mean like other things go there like navigator.getBattery().then() where this one actually exists but is barely used on the web, this one shows statuses about the battery of the device, more information and more on MDN if you are curious.

share | improve this answer | |

Not the answer you're looking for? Browse other questions tagged javascript or ask your own question.