Javascript Resolve Promise Execute Function Again if Condition

JavaScript Promise Tutorial – How to Resolve or Reject Promises in JS

Hopesouthward are important building blocks for asynchronous operations in JavaScript. Y'all may think that promises are not so easy to understand, acquire, and work with. And trust me, yous are not solitary!

Promises are challenging for many spider web developers, even after spending years working with them.

In this article, I want to try to alter that perception while sharing what I've learned about JavaScript Promises over the last few years. Hope you observe it useful.

What is a Promise in JavaScript?

A Hope is a special JavaScript object. It produces a value after an asynchronous (aka, async) performance completes successfully, or an error if information technology does not consummate successfully due to fourth dimension out, network error, and so on.

Successful call completions are indicated by the resolve part call, and errors are indicated past the decline part call.

You tin can create a hope using the promise constructor like this:

                allow promise = new Promise(function(resolve, refuse) {         // Brand an asynchronous phone call and either resolve or turn down });              

In almost cases, a promise may be used for an asynchronous operation. Even so, technically, you tin resolve/reject on both synchronous and asynchronous operations.

Hang on, don't nosotros accept callback functions for async operations?

Oh, yes! That's right. We have callback functions in JavaScript. Merely, a callback is not a special thing in JavaScript. Information technology is a regular role that produces results afterwards an asynchronous call completes (with success/error).

The word 'asynchronous' means that something happens in the time to come, not right now. Normally, callbacks are just used when doing things like network calls, or uploading/downloading things, talking to databases, and so on.

While callbacks are helpful, there is a huge downside to them equally well. At times, we may have one callback inside some other callback that's in however another callback so on. I'm serious! Let'south understand this "callback hell" with an example.

How to Avert Callback Hell – PizzaHub Case

Let's social club a Veg Margherita pizza 🍕 from the PizzaHub. When nosotros place the order, PizzaHub automatically detects our location, finds a nearby pizza restaurant, and finds if the pizza we are request for is available.

If information technology's available, it detects what kind of beverages nosotros become for complimentary along with the pizza, and finally, information technology places the order.

If the gild is placed successfully, we get a message with a confirmation.

So how exercise nosotros code this using callback functions? I came upwardly with something like this:

                function orderPizza(blazon, proper noun) {          // Query the pizzahub for a shop     query(`/api/pizzahub/`, function(outcome, error){        if (!error) {            let shopId = outcome.shopId;                        // Go the store and query pizzas            query(`/api/pizzahub/pizza/${shopid}`, role(result, mistake){                if (!error) {                    permit pizzas = result.pizzas;                                        // Find if my pizza is availavle                    permit myPizza = pizzas.find((pizza) => {                        return (pizza.type===blazon && pizza.name===proper noun);                    });                                        // Check for the complimentary beverages                    query(`/api/pizzahub/beverages/${myPizza.id}`, function(consequence, error){                        if (!error) {                            permit drinkable = effect.id;                                                        // Ready an order                            query(`/api/order`, {'type': type, 'proper name': name, 'drinkable': beverage}, part(result, error){                               if (!error) {                                   console.log(`Your order of ${blazon} ${proper noun} with ${drinkable} has been placed`);                               } else {                                   console.log(`Bad luck, No Pizza for you today!`);                               }                            });                         }                    })                }            });        }      }); }  // Phone call the orderPizza method orderPizza('veg', 'margherita');              

Let's have a close await at the orderPizza function in the higher up code.

It calls an API to go your nearby pizza shop's id. Subsequently that, it gets the list of pizzas available in that eating place. Information technology checks if the pizza nosotros are request for is constitute and makes another API call to discover the beverages for that pizza. Finally the guild API places the order.

Here we use a callback for each of the API calls. This leads us to use another callback inside the previous, and so on.

This means nosotros get into something nosotros call (very expressively) Callback Hell. And who wants that? It also forms a code pyramid which is non but confusing but also fault-prone.

callback-hell
Sit-in of callback hell and pyramid

In that location are a few ways to come out of (or non get into) callback hell. The most common one is by using a Promise or async part. Still, to sympathise async functions well, y'all need to have a fair agreement of Promisedue south get-go.

So allow's become started and dive into promises.

Agreement Promise States

Only to review, a hope can be created with the constructor syntax, like this:

                allow promise = new Promise(part(resolve, pass up) {   // Code to execute });              

The constructor function takes a function as an argument. This function is called the executor role.

                // Executor part passed to the  // Promise constructor every bit an argument function(resolve, pass up) {     // Your logic goes hither... }              

The executor role takes two arguments, resolve and reject. These are the callbacks provided by the JavaScript linguistic communication. Your logic goes inside the executor function that runs automatically when a new Hope is created.

For the hope to be constructive, the executor part should phone call either of the callback functions, resolve or refuse. We will learn more than virtually this in item in a while.

The new Promise() constructor returns a hope object. As the executor office needs to handle async operations, the returned hope object should be capable of informing when the execution has been started, completed (resolved) or retuned with error (rejected).

A promise object has the following internal backdrop:

  1. state – This belongings can have the following values:
  • pending: Initially when the executor part starts the execution.
  • fulfilled: When the promise is resolved.
  • rejected: When the promise is rejected.
states_1
Hope states

2.result – This property can have the following values:

  • undefined: Initially when the land value is pending.
  • value: When resolve(value) is called.
  • error: When reject(fault) is called.

These internal properties are code-inaccessible just they are inspectable. This means that we will exist able to audit the state and outcome property values using the debugger tool, merely nosotros will non be able to access them directly using the programme.

promise_state_inspect
Able to audit the internal properties of a promise

A promise'southward country can be awaiting, fulfilled or rejected. A hope that is either resolved or rejected is called settled.

states_2
A settled promise is either fulfilled or rejected

How promises are resolved and rejected

Here is an example of a promise that will be resolved (fulfilled state) with the value I am done immediately.

                let promise = new Promise(function(resolve, reject) {     resolve("I am done"); });              

The promise below will be rejected (rejected state) with the error message Something is non right!.

                let promise = new Promise(role(resolve, reject) {     reject(new Error('Something is not right!')); });              

An of import point to notation:

A Hope executor should call only one resolve or 1 reject. Once one state is changed (pending => fulfilled or awaiting => rejected), that'south all. Whatever farther calls to resolve or reject will be ignored.
                let hope = new Promise(function(resolve, reject) {   resolve("I am surely going to get resolved!");    reject(new Error('Will this be ignored?')); // ignored   resolve("Ignored?"); // ignored });              

In the instance above, but the first one to resolve will be called and the rest will exist ignored.

How to handle a Promise once you've created information technology

A Promise uses an executor office to complete a chore (more often than not asynchronously). A consumer function (that uses an result of the promise) should get notified when the executor role is done with either resolving (success) or rejecting (mistake).

The handler methods, .and then(), .take hold of() and .finally(), help to create the link between the executor and the consumer functions and so that they can be in sync when a promise resolvesouth or rejects.

consumer_executor
The executor and consumer functions

How to Use the .then() Promise Handler

The .then() method should be chosen on the promise object to handle a result (resolve) or an fault (reject).

Information technology accepts ii functions as parameters. Usually, the .and then() method should be called from the consumer function where you lot would like to know the result of a promise'southward execution.

                promise.then(   (issue) => {       console.log(result);   },   (error) => {       panel.log(error);   } );              

If you are interested simply in successful outcomes, y'all tin merely pass one argument to it, like this:

                promise.then(   (effect) => {        console.log(consequence);   } );              

If you lot are interested only in the fault issue, yous can pass null for the first statement, like this:

                promise.so(   cypher,   (error) => {        console.log(mistake)   } );              

However, yous tin can handle errors in a improve way using the .catch() method that nosotros volition encounter in a minute.

Let's expect at a couple of examples of handling results and errors using the .then and .catch handlers. Nosotros will brand this learning a scrap more fun with a few existent asynchronous requests. Nosotros will use the PokeAPI to get information about Pokémon and resolve/decline them using Promises.

Commencement, let us create a generic function that accepts a PokeAPI URL equally argument and returns a Hope. If the API call is successful, a resolved promise is returned. A rejected promise is returned for whatever kind of errors.

We will exist using this office in several examples from now on to get a hope and work on information technology.

                  function getPromise(URL) {   let promise = new Promise(part (resolve, reject) {     let req = new XMLHttpRequest();     req.open("GET", URL);     req.onload = role () {       if (req.status == 200) {         resolve(req.response);       } else {         reject("In that location is an Error!");       }     };     req.send();   });   return hope; }                
Utility method to get a Hope

Case 1: Go 50 Pokémon's data:

                const ALL_POKEMONS_URL = 'https://pokeapi.co/api/v2/pokemon?limit=l';  // We take discussed this function already! let promise = getPromise(ALL_POKEMONS_URL);  const consumer = () => {     hope.and so(         (result) => {             console.log({result}); // Log the result of l Pokemons         },         (error) => {             // As the URL is a valid one, this will not exist called.             console.log('We have encountered an Error!'); // Log an error     }); }  consumer();              

Example two: Let's attempt an invalid URL

                const POKEMONS_BAD_URL = 'https://pokeapi.co/api/v2/pokemon-bad/';  // This will turn down as the URL is 404 let hope = getPromise(POKEMONS_BAD_URL);  const consumer = () => {     hope.and so(         (result) => {             // The promise didn't resolve. Hence, information technology will             // non be executed.             console.log({result});         },         (error) => {             // A rejected prmise will execute this             panel.log('Nosotros have encountered an Error!'); // Log an error         }     ); }  consumer();              

How to Use the .catch() Hope Handler

You can use this handler method to handle errors (rejections) from promises. The syntax of passing nada as the first argument to the .and then() is non a corking way to handle errors. So we take .catch() to do the same chore with some bang-up syntax:

                // This will reject as the URL is 404 permit hope = getPromise(POKEMONS_BAD_URL);  const consumer = () => {     promise.catch(error => console.log(mistake)); }  consumer();              

If we throw an Error similar new Error("Something wrong!") instead of calling the reject from the promise executor and handlers, information technology will yet be treated as a rejection. Information technology means that this will exist caught by the .catch handler method.

This is the same for any synchronous exceptions that happen in the promise executor and handler functions.

Here is an example where it will be treated like a decline and the .catch handler method will be chosen:

                new Promise((resolve, reject) => {   throw new Error("Something is wrong!");// No reject call }).catch((mistake) => panel.log(fault));                              

How to Use the .finally() Promise Handler

The .finally() handler performs cleanups similar stopping a loader, closing a alive connection, then on. The finally() method will be called irrespective of whether a promise resolves or turn downs. It passes through the result or error to the next handler which tin can phone call a .then() or .grab() again.

Hither is an case that'll help yous understand all three methods together:

                allow loading = true; loading && console.log('Loading...');  // Gatting Hope hope = getPromise(ALL_POKEMONS_URL);  promise.finally(() => {     loading = imitation;     console.log(`Promise Settled and loading is ${loading}`); }).and then((result) => {     console.log({outcome}); }).take hold of((error) => {     console.log(error) });              

To explain a chip further:

  • The .finally() method makes loading simulated.
  • If the promise resolves, the .and so() method will be called. If the promise rejects with an mistake, the .catch() method will exist called. The .finally() will exist called irrespective of the resolve or reject.

What is the Promise Chain?

Thepromise.then() telephone call always returns a promise. This hope will have the state as awaiting and result every bit undefined. It allows u.s. to call the adjacent .then method on the new promise.

When the first .then method returns a value, the side by side .then method can receive that. The 2d ane can at present pass to the tertiary .so() and so on. This forms a concatenation of .then methods to pass the promises down. This phenomenon is called the Promise Chain.

image-105
Promise Chain

Here is an example:

                allow hope = getPromise(ALL_POKEMONS_URL);  promise.then(result => {     let onePokemon = JSON.parse(upshot).results[0].url;     return onePokemon; }).then(onePokemonURL => {     console.log(onePokemonURL); }).catch(error => {     console.log('In the grab', fault); });              

Here nosotros start get a promise resolved and then extract the URL to reach the first Pokémon. We and so return that value and it volition be passed equally a promise to the side by side .then() handler part. Hence the output,

                https://pokeapi.co/api/v2/pokemon/ane/              

The .so method tin can render either:

  • A value (nosotros have seen this already)
  • A brand new hope.

It can also throw an error.

Here is an example where we take created a promise chain with the .so methods which returns results and a new promise:

                // Hope Concatenation with multiple then and grab let promise = getPromise(ALL_POKEMONS_URL);  promise.then(event => {     let onePokemon = JSON.parse(result).results[0].url;     return onePokemon; }).then(onePokemonURL => {     console.log(onePokemonURL);     return getPromise(onePokemonURL); }).and then(pokemon => {     console.log(JSON.parse(pokemon)); }).catch(error => {     console.log('In the catch', error); });              

In the starting time .so call we excerpt the URL and render it as a value. This URL will be passed to the 2d .then phone call where we are returning a new promise taking that URL as an argument.

This hope will be resolved and passed down to the chain where we get the information about the Pokémon. Here is the output:

image-159
Output of the promise chain call

In case in that location is an error or a promise rejection, the .catch method in the chain will be called.

A indicate to note: Calling .then multiple times doesn't course a Promise chain. You may end upward doing something similar this only to introduce a bug in the code:

                allow promise = getPromise(ALL_POKEMONS_URL);  hope.and then(result => {     let onePokemon = JSON.parse(consequence).results[0].url;     return onePokemon; }); promise.then(onePokemonURL => {     console.log(onePokemonURL);     return getPromise(onePokemonURL); }); promise.then(pokemon => {     console.log(JSON.parse(pokemon)); });                              

We call the .then method three times on the same promise, but nosotros don't pass the promise down. This is different than the hope chain. In the in a higher place example, the output will be an error.

image-160

How to Handle Multiple Promises

Apart from the handler methods (.then, .catch, and .finally), at that place are six static methods available in the Promise API. The outset four methods accept an assortment of promises and run them in parallel.

  1. Promise.all
  2. Promise.whatsoever
  3. Hope.allSettled
  4. Hope.race
  5. Promise.resolve
  6. Hope.reject

Let's become through each one.

The Promise.all() method

Hope.all([promises]) accepts a collection (for instance, an array) of promises equally an argument and executes them in parallel.

This method waits for all the promises to resolve and returns the assortment of promise results. If whatsoever of the promises reject or execute to neglect due to an fault, all other promise results will be ignored.

Let's create three promises to become data about three Pokémons.

                const BULBASAUR_POKEMONS_URL = 'https://pokeapi.co/api/v2/pokemon/bulbasaur'; const RATICATE_POKEMONS_URL = 'https://pokeapi.co/api/v2/pokemon/raticate'; const KAKUNA_POKEMONS_URL = 'https://pokeapi.co/api/v2/pokemon/kakuna';   let promise_1 = getPromise(BULBASAUR_POKEMONS_URL); let promise_2 = getPromise(RATICATE_POKEMONS_URL); let promise_3 = getPromise(KAKUNA_POKEMONS_URL);              

Use the Promise.all() method by passing an array of promises.

                Promise.all([promise_1, promise_2, promise_3]).then(result => {     console.log({result}); }).take hold of(error => {     console.log('An Error Occured'); });              

Output:

image-161

Every bit you lot see in the output, the result of all the promises is returned. The fourth dimension to execute all the promises is equal to the max fourth dimension the promise takes to run.

The Hope.any() method

Promise.any([promises]) - Similar to the all() method, .any() also accepts an array of promises to execute them in parallel. This method doesn't wait for all the promises to resolve. It is done when any one of the promises is settled.

                                  Promise.whatever([promise_1, promise_2, promise_3]).then(consequence => {      console.log(JSON.parse(upshot));  }).grab(error => {      panel.log('An Error Occured');  });              

The output would exist the consequence of whatever of the resolved promises:

image-162

The Promise.allSettled() method

romise.allSettled([promises]) - This method waits for all promises to settle(resolve/reject) and returns their results as an assortment of objects. The results will contain a state (fulfilled/rejected) and value, if fulfilled. In example of rejected condition, it volition return a reason for the error.

Here is an example of all fulfilled promises:

                Promise.allSettled([promise_1, promise_2, promise_3]).then(result => {     console.log({result}); }).catch(mistake => {     console.log('There is an Error!'); });              

Output:

image-163

If any of the promises rejects, say, the promise_1,

                let promise_1 = getPromise(POKEMONS_BAD_URL);              
image-164

The Hope.race() method

Promise.race([promises]) – It waits for the first (quickest) hope to settle, and returns the result/error accordingly.

                Hope.race([promise_1, promise_2, promise_3]).and then(result => {     console.log(JSON.parse(result)); }).grab(fault => {     console.log('An Error Occured'); });              

Output the fastest hope that got resolved:

image-165

The Hope.resolve/reject methods

Hope.resolve(value) – Information technology resolves a promise with the value passed to information technology. It is the same equally the following:

                let promise = new Promise(resolve => resolve(value));              

Promise.decline(fault) – It rejects a hope with the error passed to information technology. It is the same equally the post-obit:

                let hope = new Promise((resolve, reject) => reject(error));              

Can we rewrite the PizzaHub example with Promises?

Sure, allow's do it. Let us assume that the query method will return a promise. Here is an example query() method. In existent life, this method may talk to a database and render results. In this example, information technology is very much hard-coded but serves the aforementioned purpose.

                function query(endpoint) {   if (endpoint === `/api/pizzahub/`) {     return new Hope((resolve, turn down) => {       resolve({'shopId': '123'});     })   } else if (endpoint.indexOf('/api/pizzahub/pizza/') >=0) {     return new Promise((resolve, turn down) => {       resolve({pizzas: [{'type': 'veg', 'name': 'margherita', 'id': '123'}]});     })   } else if (endpoint.indexOf('/api/pizzahub/beverages') >=0) {     return new Hope((resolve, decline) => {       resolve({id: 'ten', 'blazon': 'veg', 'proper noun': 'margherita', 'beverage': 'coke'});     })   } else if (endpoint === `/api/order`) {     return new Promise((resolve, reject) => {       resolve({'type': 'veg', 'name': 'margherita', 'drink': 'coke'});     })   } }              

Side by side is the refactoring of our callback hell. To practise that, first, we will create a few logical functions:

                // Returns a shop id permit getShopId = result => result.shopId;  // Returns a promise with pizza list for a shop let getPizzaList = shopId => {   const url = `/api/pizzahub/pizza/${shopId}`;   render query(url); }  // Returns a promise with pizza that matches the customer asking let getMyPizza = (result, type, name) => {   let pizzas = result.pizzas;   allow myPizza = pizzas.find((pizza) => {     return (pizza.type===type && pizza.name===proper noun);   });   const url = `/api/pizzahub/beverages/${myPizza.id}`;   return query(url); }  // Returns a promise later Placing the society allow performOrder = result => {   let potable = consequence.id;    return query(`/api/order`, {'type': result.type, 'proper name': result.name, 'drinkable': result.drink}); }  // Ostend the club allow confirmOrder = result => {     panel.log(`Your order of ${issue.type} ${result.name} with ${result.drink} has been placed!`); }              

Employ these functions to create the required promises. This is where you should compare with the callback hell example. This is so nice and elegant.

                function orderPizza(type, name) {   query(`/api/pizzahub/`)   .then(result => getShopId(result))   .then(shopId => getPizzaList(shopId))   .then(effect => getMyPizza(result, type, proper noun))   .then(result => performOrder(result))   .and so(result => confirmOrder(outcome))   .catch(office(fault){     panel.log(`Bad luck, No Pizza for y'all today!`);   }) }              

Finally, call the orderPizza() method by passing the pizza type and name, like this:

                orderPizza('veg', 'margherita');                              

What'southward next from here?

If you are here and take read through most of the lines in a higher place, congratulations! You should now accept a meliorate grip of JavaScript Promises. All the examples used in this article are in this GitHub repository.

Next, y'all should learn near the async function in JavaScript which simplifies things farther. The concept of JavaScript promises is best learned by writing minor examples and building on pinnacle of them.

Irrespective of the framework or library (Angular, React, Vue, and so on) we use, async operations are unavoidable. This means that we have to empathise promises to brand things work better.

Too, I'm sure you will notice the usage of the fetch method much easier now:

                fetch('/api/user.json') .then(function(response) {     return response.json(); }) .and then(role(json) {     panel.log(json); // {"proper name": "tapas", "blog": "freeCodeCamp"} });              
  • The fetch method returns a promise. So we can call the .and so handler method on information technology.
  • The rest is about the promise chain which nosotros learned in this article.

Before nosotros end...

Cheers for reading this far! Let's connect. Yous tin can @ me on Twitter (@tapasadhikary) with comments.

You may also like these other articles:

  • JavaScript undefined and zilch: Let'southward talk about it one last time!
  • JavaScript: Equality comparison with ==, === and Object.is
  • The JavaScript `this` Keyword + v Primal Bounden Rules Explained for JS Beginners
  • JavaScript TypeOf – How to Cheque the Type of a Variable or Object in JS

That'south all for now. See you again with my next article presently. Until then, please take good care of yourself.



Learn to lawmaking for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Go started

horngreentrion.blogspot.com

Source: https://www.freecodecamp.org/news/javascript-promise-tutorial-how-to-resolve-or-reject-promises-in-js/

0 Response to "Javascript Resolve Promise Execute Function Again if Condition"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel