Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the function then() mean in JavaScript?

Tags:

javascript

I’ve been seeing code that looks like:

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

Where does then() come from?

like image 975
Kay Pale Avatar asked Oct 07 '10 17:10

Kay Pale


People also ask

When can I use then in JavaScript?

The then() method in JavaScript has been defined in the Promise API and is used to deal with asynchronous tasks such as an API call. Previously, callback functions were used instead of this function which made the code difficult to maintain.

What is then and catch in JavaScript?

The main difference between the forms promise. then(success, error) and promise. then(success). catch(error) is that in case if success callback returns a rejected promise, then only the second form is going to catch that rejection.

What are the 3 types of functions in JavaScript?

There are 3 ways of writing a function in JavaScript: Function Declaration. Function Expression. Arrow Function.

How do you use then promise?

If you call then() on a promise that is already fulfilled, JavaScript will immediately call onFulfilled() . const promise = new Promise(function executor(resolve, reject) { // Fulfill the promise with value '42' after 100 ms. setTimeout(() => resolve(42), 100); }); promise. then(value => { value; // 42 });


1 Answers

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 our application. With callbacks, the code might look something like the following (assuming a 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 fetch information about the current user, and then finally get the list of items for the current user. Each xhrGET call takes a callback function that is executed when the server responds.

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 each xhrGET call to tell it what it needs to do in case of an error. If we wanted to have just one common 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 success handler and an error handler.
  3. The success or the error handler in the then function will be called only once, after the 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 next handler (success or error) will be called only after that request is finished.

So the previous example code might translate to something like the following, using promises 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 of functionality, like having a service make a server call, do some postprocessing of the data, and then return the processed data to the controller. But when we work with promise 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 and E2 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 flow through S1, S2, and finally, S3. But in real life, things are never that smooth. P1 might encounter 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 not correct, or there is no data available on the server (think empty array). In such a case, 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 have data 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 our current function, is this promise a success or a failure for the next handler in the promise chain?

If we want to trigger the success handler for the next promise in the chain, we can just return 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 the chain, 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

like image 63
Sid Avatar answered Oct 04 '22 15:10

Sid