Javascript Resolve Promise Execute Function Again if Condition

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

Promisedue south are of import building blocks for asynchronous operations in JavaScript. Y'all may call back that promises are not so easy to understand, acquire, and work with. And trust me, you are not alone!

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

In this article, I want to endeavor to change that perception while sharing what I've learned about JavaScript Promises over the terminal few years. Hope y'all find information technology useful.

What is a Promise in JavaScript?

A Hope is a special JavaScript object. Information technology produces a value after an asynchronous (aka, async) operation completes successfully, or an error if it does not complete successfully due to time out, network error, and so on.

Successful phone call completions are indicated by the resolve office phone call, and errors are indicated by the reject function call.

You can create a promise using the promise constructor similar this:

                permit hope = new Hope(function(resolve, reject) {         // Brand an asynchronous phone call and either resolve or refuse });              

In most cases, a hope may be used for an asynchronous operation. However, technically, you tin resolve/reject on both synchronous and asynchronous operations.

Hang on, don't we have callback functions for async operations?

Oh, yep! That's correct. We have callback functions in JavaScript. But, a callback is not a special matter in JavaScript. It is a regular part that produces results after an asynchronous call completes (with success/mistake).

The word 'asynchronous' means that something happens in the future, not right at present. Usually, callbacks are merely used when doing things like network calls, or uploading/downloading things, talking to databases, and then on.

While callbacks are helpful, at that place is a huge downside to them as well. At times, nosotros may have ane callback inside another callback that'south in nonetheless another callback so on. I'm serious! Let'southward understand this "callback hell" with an case.

How to Avoid Callback Hell – PizzaHub Example

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

If information technology'southward available, it detects what kind of beverages we get for free along with the pizza, and finally, it places the social club.

If the order is placed successfully, we go a message with a confirmation.

And then how do nosotros code this using callback functions? I came up with something like this:

                function orderPizza(type, proper name) {          // Query the pizzahub for a store     query(`/api/pizzahub/`, function(issue, error){        if (!mistake) {            let shopId = outcome.shopId;                        // Go the store and query pizzas            query(`/api/pizzahub/pizza/${shopid}`, office(result, mistake){                if (!fault) {                    allow pizzas = result.pizzas;                                        // Find if my pizza is availavle                    allow myPizza = pizzas.find((pizza) => {                        render (pizza.type===blazon && pizza.name===proper name);                    });                                        // Cheque for the free beverages                    query(`/api/pizzahub/beverages/${myPizza.id}`, function(result, mistake){                        if (!mistake) {                            let potable = upshot.id;                                                        // Set an gild                            query(`/api/guild`, {'type': type, 'name': name, 'beverage': drink}, function(consequence, mistake){                               if (!error) {                                   console.log(`Your guild of ${type} ${proper name} with ${drinkable} has been placed`);                               } else {                                   console.log(`Bad luck, No Pizza for you today!`);                               }                            });                         }                    })                }            });        }      }); }  // Call the orderPizza method orderPizza('veg', 'margherita');              

Let's accept a close look at the orderPizza function in the to a higher place code.

It calls an API to get your nearby pizza shop'southward id. After that, it gets the listing of pizzas available in that eating place. Information technology checks if the pizza we are asking for is found and makes another API call to notice the beverages for that pizza. Finally the guild API places the lodge.

Here nosotros utilise a callback for each of the API calls. This leads us to utilize another callback inside the previous, and then on.

This means we get into something we call (very expressively) Callback Hell. And who wants that? It also forms a code pyramid which is not only confusing just also error-prone.

callback-hell
Sit-in of callback hell and pyramid

At that place are a few ways to come out of (or non become into) callback hell. The most mutual i is by using a Hope or async function. However, to understand async functions well, you need to take a fair agreement of Promises get-go.

So permit's get started and swoop into promises.

Understanding Promise States

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

                permit promise = new Hope(function(resolve, turn down) {   // Lawmaking to execute });              

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

                // Executor function passed to the  // Promise constructor every bit an argument office(resolve, refuse) {     // Your logic goes here... }              

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

For the promise to be effective, the executor function should call either of the callback functions, resolve or reject. We will larn more than about this in detail in a while.

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

A hope object has the post-obit internal backdrop:

  1. state – This property can accept the following values:
  • awaiting: Initially when the executor function starts the execution.
  • fulfilled: When the hope is resolved.
  • rejected: When the promise is rejected.
states_1
Hope states

2.result – This property can have the post-obit values:

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

These internal properties are lawmaking-inaccessible simply they are inspectable. This means that nosotros will be able to inspect the state and result belongings values using the debugger tool, only we will not exist able to admission them direct using the program.

promise_state_inspect
Able to inspect the internal properties of a hope

A promise's state tin exist pending, fulfilled or rejected. A promise that is either resolved or rejected is called settled.

states_2
A settled hope is either fulfilled or rejected

How promises are resolved and rejected

Here is an instance of a promise that volition be resolved (fulfilled country) with the value I am done immediately.

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

The hope below will be rejected (rejected country) with the error message Something is not correct!.

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

An important point to note:

A Hope executor should call but one resolve or i decline. In one case one state is changed (awaiting => fulfilled or pending => rejected), that's all. Any further calls to resolve or pass up will be ignored.
                let promise = new Promise(function(resolve, reject) {   resolve("I am surely going to become resolved!");    refuse(new Error('Volition this exist ignored?')); // ignored   resolve("Ignored?"); // ignored });              

In the example to a higher place, simply the kickoff one to resolve will be called and the residual volition exist ignored.

How to handle a Promise in one case you've created it

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

The handler methods, .so(), .catch() and .finally(), help to create the link between the executor and the consumer functions then that they can be in sync when a hope resolves or rejects.

consumer_executor
The executor and consumer functions

How to Employ the .then() Promise Handler

The .then() method should exist called on the promise object to handle a result (resolve) or an error (reject).

It accepts two functions as parameters. Unremarkably, the .then() method should exist called from the consumer function where you would like to know the outcome of a hope's execution.

                promise.and then(   (result) => {       console.log(consequence);   },   (error) => {       console.log(mistake);   } );              

If you lot are interested but in successful outcomes, y'all can just pass 1 argument to information technology, similar this:

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

If you are interested only in the error effect, you can pass nix for the first argument, similar this:

                promise.and then(   null,   (mistake) => {        console.log(error)   } );              

Even so, you can handle errors in a better fashion using the .catch() method that we will run across in a minute.

Permit's look at a couple of examples of handling results and errors using the .so and .catch handlers. We will make this learning a fleck more fun with a few real asynchronous requests. We will use the PokeAPI to get information about Pokémon and resolve/refuse them using Promises.

First, allow united states of america create a generic function that accepts a PokeAPI URL every bit statement and returns a Promise. If the API telephone call is successful, a resolved promise is returned. A rejected promise is returned for any kind of errors.

Nosotros volition be using this function in several examples from now on to go a promise and piece of work on it.

                  part getPromise(URL) {   let promise = new Hope(function (resolve, refuse) {     let req = new XMLHttpRequest();     req.open("Get", URL);     req.onload = part () {       if (req.status == 200) {         resolve(req.response);       } else {         reject("There is an Error!");       }     };     req.send();   });   render promise; }                
Utility method to get a Promise

Example 1: Get 50 Pokémon'due south information:

                const ALL_POKEMONS_URL = 'https://pokeapi.co/api/v2/pokemon?limit=50';  // We have discussed this function already! allow promise = getPromise(ALL_POKEMONS_URL);  const consumer = () => {     promise.and then(         (issue) => {             console.log({result}); // Log the result of 50 Pokemons         },         (fault) => {             // As the URL is a valid ane, this volition not be called.             panel.log('We accept encountered an Fault!'); // Log an error     }); }  consumer();              

Example two: Allow'south try an invalid URL

                const POKEMONS_BAD_URL = 'https://pokeapi.co/api/v2/pokemon-bad/';  // This volition refuse as the URL is 404 allow promise = getPromise(POKEMONS_BAD_URL);  const consumer = () => {     promise.then(         (effect) => {             // The hope didn't resolve. Hence, it will             // not be executed.             console.log({effect});         },         (mistake) => {             // A rejected prmise will execute this             panel.log('We have encountered an Error!'); // Log an error         }     ); }  consumer();              

How to Use the .catch() Hope Handler

You can apply this handler method to handle errors (rejections) from promises. The syntax of passing aught as the first argument to the .then() is not a keen way to handle errors. So we have .take hold of() to do the same job with some nifty syntax:

                // This will pass up equally the URL is 404 allow promise = getPromise(POKEMONS_BAD_URL);  const consumer = () => {     promise.catch(error => console.log(error)); }  consumer();              

If nosotros throw an Error like new Error("Something wrong!") instead of calling the turn down from the promise executor and handlers, it volition still be treated as a rejection. It ways that this will exist defenseless 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 exist treated like a reject and the .catch handler method volition exist chosen:

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

How to Use the .finally() Promise Handler

The .finally() handler performs cleanups like stopping a loader, endmost a live connection, so on. The finally() method will be called irrespective of whether a promise resolves or pass upsouthward. It passes through the issue or error to the next handler which can phone call a .then() or .grab() again.

Here is an example that'll help you empathize all three methods together:

                let loading = true; loading && console.log('Loading...');  // Gatting Promise promise = getPromise(ALL_POKEMONS_URL);  promise.finally(() => {     loading = faux;     console.log(`Promise Settled and loading is ${loading}`); }).and then((effect) => {     console.log({result}); }).grab((error) => {     console.log(error) });              

To explicate a bit further:

  • The .finally() method makes loading faux.
  • If the promise resolves, the .then() method volition be called. If the promise rejects with an error, the .take hold of() method will be called. The .finally() will be chosen irrespective of the resolve or pass up.

What is the Promise Concatenation?

Thepromise.then() call always returns a promise. This promise will have the state as pending and outcome as undefined. It allows us to call the side by side .and then method on the new promise.

When the showtime .then method returns a value, the next .then method can receive that. The second one can now pass to the third .then() then on. This forms a chain of .so methods to pass the promises down. This phenomenon is called the Hope Chain.

image-105
Promise Chain

Here is an example:

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

Here we first get a promise resolved so extract the URL to reach the kickoff Pokémon. We so render that value and it will exist passed every bit a promise to the adjacent .then() handler function. Hence the output,

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

The .so method can return either:

  • A value (we accept seen this already)
  • A brand new promise.

Information technology can also throw an fault.

Here is an instance where we have created a promise chain with the .then methods which returns results and a new promise:

                // Promise Concatenation with multiple then and take hold of let promise = getPromise(ALL_POKEMONS_URL);  hope.then(issue => {     let onePokemon = JSON.parse(issue).results[0].url;     return onePokemon; }).then(onePokemonURL => {     console.log(onePokemonURL);     render getPromise(onePokemonURL); }).then(pokemon => {     console.log(JSON.parse(pokemon)); }).catch(error => {     console.log('In the catch', fault); });              

In the start .and then call nosotros extract the URL and render it as a value. This URL will be passed to the second .and so call where nosotros are returning a new hope taking that URL as an statement.

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

image-159
Output of the promise chain phone call

In case there is an error or a promise rejection, the .take hold of method in the chain will be chosen.

A point to notation: Calling .then multiple times doesn't class a Promise chain. Yous may end up doing something similar this only to introduce a problems in the code:

                let promise = getPromise(ALL_POKEMONS_URL);  promise.so(result => {     let onePokemon = JSON.parse(event).results[0].url;     return onePokemon; }); promise.then(onePokemonURL => {     panel.log(onePokemonURL);     render getPromise(onePokemonURL); }); promise.so(pokemon => {     console.log(JSON.parse(pokemon)); });                              

We call the .and so method three times on the same promise, merely we don't pass the promise down. This is unlike than the promise chain. In the higher up example, the output will be an error.

image-160

How to Handle Multiple Promises

Apart from the handler methods (.and so, .grab, and .finally), there are six static methods available in the Promise API. The start four methods accept an array of promises and run them in parallel.

  1. Promise.all
  2. Promise.any
  3. Promise.allSettled
  4. Promise.race
  5. Hope.resolve
  6. Hope.pass up

Allow'due south get through each one.

The Promise.all() method

Promise.all([promises]) accepts a collection (for example, an array) of promises as an statement and executes them in parallel.

This method waits for all the promises to resolve and returns the array of hope results. If whatever of the promises refuse or execute to fail due to an mistake, all other promise results will be ignored.

Permit'due south create iii promises to get information most iii 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);              

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

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

Output:

image-161

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

The Promise.whatsoever() method

Hope.any([promises]) - Like 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 washed when whatever ane of the promises is settled.

                                  Promise.whatever([promise_1, promise_2, promise_3]).then(outcome => {      console.log(JSON.parse(result));  }).catch(error => {      console.log('An Mistake Occured');  });              

The output would be the outcome of any of the resolved promises:

image-162

The Hope.allSettled() method

romise.allSettled([promises]) - This method waits for all promises to settle(resolve/decline) and returns their results equally an assortment of objects. The results will comprise a land (fulfilled/rejected) and value, if fulfilled. In case of rejected condition, information technology volition return a reason for the fault.

Hither is an example of all fulfilled promises:

                Promise.allSettled([promise_1, promise_2, promise_3]).then(outcome => {     console.log({effect}); }).grab(error => {     console.log('In that location 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 offset (quickest) promise to settle, and returns the consequence/error appropriately.

                Hope.race([promise_1, promise_2, promise_3]).then(event => {     console.log(JSON.parse(result)); }).catch(error => {     panel.log('An Error Occured'); });              

Output the fastest promise that got resolved:

image-165

The Promise.resolve/reject methods

Promise.resolve(value) – Information technology resolves a promise with the value passed to it. It is the same as the following:

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

Promise.reject(error) – It rejects a promise with the mistake passed to it. Information technology is the same as the following:

                let promise = new Hope((resolve, turn down) => refuse(fault));              

Tin we rewrite the PizzaHub example with Promises?

Sure, let's do information technology. Permit u.s. assume that the query method will return a promise. Hither is an example query() method. In real life, this method may talk to a database and render results. In this case, information technology is very much hard-coded but serves the same purpose.

                part query(endpoint) {   if (endpoint === `/api/pizzahub/`) {     return new Promise((resolve, reject) => {       resolve({'shopId': '123'});     })   } else if (endpoint.indexOf('/api/pizzahub/pizza/') >=0) {     render new Promise((resolve, reject) => {       resolve({pizzas: [{'type': 'veg', 'name': 'margherita', 'id': '123'}]});     })   } else if (endpoint.indexOf('/api/pizzahub/beverages') >=0) {     return new Promise((resolve, reject) => {       resolve({id: '10', 'type': 'veg', 'proper name': 'margherita', 'drinkable': 'coke'});     })   } else if (endpoint === `/api/society`) {     return new Promise((resolve, decline) => {       resolve({'type': 'veg', 'proper name': 'margherita', 'drinkable': 'coke'});     })   } }              

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

                // Returns a store id let getShopId = result => upshot.shopId;  // Returns a promise with pizza list for a shop permit getPizzaList = shopId => {   const url = `/api/pizzahub/pizza/${shopId}`;   return query(url); }  // Returns a promise with pizza that matches the client request permit getMyPizza = (result, type, name) => {   let pizzas = consequence.pizzas;   let myPizza = pizzas.detect((pizza) => {     return (pizza.type===type && pizza.proper noun===name);   });   const url = `/api/pizzahub/beverages/${myPizza.id}`;   return query(url); }  // Returns a promise later Placing the lodge allow performOrder = effect => {   permit beverage = result.id;    return query(`/api/club`, {'blazon': issue.blazon, 'proper noun': consequence.proper name, 'beverage': result.beverage}); }  // Confirm the order let confirmOrder = result => {     panel.log(`Your order of ${effect.blazon} ${upshot.name} with ${consequence.beverage} has been placed!`); }              

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

                part orderPizza(type, proper noun) {   query(`/api/pizzahub/`)   .then(upshot => getShopId(result))   .and so(shopId => getPizzaList(shopId))   .and then(consequence => getMyPizza(effect, type, name))   .then(result => performOrder(result))   .so(result => confirmOrder(result))   .grab(function(error){     panel.log(`Bad luck, No Pizza for you lot today!`);   }) }              

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

                orderPizza('veg', 'margherita');                              

What'south side by side from here?

If y'all are here and have read through most of the lines above, congratulations! You should now have a ameliorate grip of JavaScript Promises. All the examples used in this article are in this GitHub repository.

Next, you should acquire nearly the async function in JavaScript which simplifies things further. The concept of JavaScript promises is best learned by writing pocket-size examples and building on top of them.

Irrespective of the framework or library (Athwart, React, Vue, and so on) nosotros utilise, async operations are unavoidable. This means that we have to understand promises to make things piece of work amend.

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

                fetch('/api/user.json') .and then(function(response) {     render response.json(); }) .then(function(json) {     console.log(json); // {"proper name": "tapas", "web log": "freeCodeCamp"} });              
  • The fetch method returns a promise. So we can call the .so handler method on it.
  • The rest is about the promise chain which we learned in this commodity.

Earlier nosotros terminate...

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

You may also similar these other articles:

  • JavaScript undefined and cipher: Let's talk about it one last fourth dimension!
  • JavaScript: Equality comparison with ==, === and Object.is
  • The JavaScript `this` Keyword + v Key Binding Rules Explained for JS Beginners
  • JavaScript TypeOf – How to Check the Type of a Variable or Object in JS

That's all for now. Run across you again with my next article presently. Until then, please have good care of yourself.



Acquire to lawmaking for free. freeCodeCamp'south open source curriculum has helped more than 40,000 people get jobs equally developers. Become started

clarkwies1993.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"

Postar um comentário

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel