Hi there and thanks for your article. I didn't know about the Promise.allSettled and your article just made me discover this!
I think your example:
functiongetMoneyBack(money,callback){if(typeofmoney!=='number'){callback(null,newError('money is not a number'))}else{callback(money)}}constmoney=getMoneyBack(1200)console.log(money)
Is missing its callback:
functiongetMoneyBack(money,callback){if(typeofmoney!=='number'){callback(null,newError('money is not a number'))}else{returncallback(money)}}constmoney=getMoneyBack(1200,function(money){returnmoney*1.2;// applying some increase})console.log(money);
Thanks for this. One thing I've had issues with in the past is handling different errors when you have a long promise chain hitting different APIs.
In my case, each error needed to be handled differently, and the promise chain needs to be stopped if something fails. I couldn't use Promise.all in this case since promise2 relied on promise1 and promise3 relied on promise2.
You can catch errors when chaining promise in a single catch.
fetch("https://jsonplaceholder.typicode.com/posts/1").then(function(response){returnresponse.json();}).then(function(post){returnfetch(`https://jsonplaceholder.typicode.com/users/${post.userId}`);}).then(function(response){returnresponse.json();}).then(function(user){console.log("User who has posted the first post");console.log(user);}).catch(function(error){console.error("An error occurred");console.error(error);});
As you can see, I'm only using one catch, and it will catch any error thrown in any branch of the chain. Try removing a character from one of the URLs to trigger an error and see the output.
You could even use async/await keywords to modelize your problem in a more procedural form.
"use strict";constfetch=require("node-fetch");asyncfunctionmain(){try{consturl="https://jsonplaceholder.typicode.com";constpostResponse=awaitfetch(`${url}/posts/1`)constpost=awaitpostResponse.json();constuserResponse=awaitfetch(`${url}/users/${post.userId}`);constuser=awaituserResponse.json();console.log("User who has posted the first post");console.log(user);}catch(error){console.error("An error occurred");console.error(error);}}main();
Thanks for the reply. I knew about the single catch, but I was wondering for a more complex example what people would do. Say instead of hitting the same API server for each call, you are hitting different ones, each with their own error responses.
I guess you could have a single catch, and have a unique handler for each error type, but I found this was not as clean as I liked.
My solution to handle a scenario like this was storing an any errors caught mid promise chain in a variable and handling that error in a more procedural manner. I updated your example with how I would do it. Using async/await makes this way of handling errors cleaner than doing everything in the catch block imo.
constfetch=require("node-fetch");asyncfunctionmain(){try{consturl="https://jsonplaceholder.typicode.com";leterrconstpostResponse=awaitfetch(`${url}/posts/1`).catch(error=>err=error)if(err){/* Handle the posts error and return */}constpost=awaitpostResponse.json()constuserResponse=awaitfetch(`${url}/users/${post.userId}`).catch(error=>err=error);if(err){/* Handle the users error and return */}constuser=awaituserResponse.json();console.log("User who has posted the first post");console.log(user);}catch(error){console.error("Handle all other errors");console.error(error);}}main();
I understand what you are trying to do. You could use custom Error subclasses which allow you to keep handling errors in the catch part while still having some control over which kind of error is thrown instead of a generic one.
"use strict";classPostResponseErrorextendsError{constructor(...parameters){super(...parameters);this.name="PostResponseError";}}classUserResponseErrorextendsError{constructor(...parameters){super(...parameters);this.name="UserResponseError";}}asyncfunctionmain(){try{consturl="https://jsonplaceholder.typicode.com";constpostResponse=awaitfetch(`${url}/posts/1`);if(!postResponse.ok){thrownewPostResponseError("Error with the response");}constpost=awaitpostResponse.json();constuserResponse=awaitfetch(`${url}/users/${post.userId}`);if(!userResponse.ok){thrownewUserResponseError("Error with the response");}constuser=awaituserResponse.json();console.log("User who has posted the first post");console.log(user);}catch(error){if(errorinstanceofPostResponseError){console.log("Error with the post response");}elseif(errorinstanceofUserResponseError){console.log("Error with the user response");}else{console.error("Unexpected error");}console.error(error);}}main();
constgetMoneyBack=(money:number):Observable<number>=>{returnnewObservable(subscriber=>{if(typeofmoney!=='number'){subscriber.error(newError('money is not a number'))}else{subscriber.next(money)subscriber.complete()}}constmoneySubscription:Subscription=getMoneyBack(1200).subscribe({next:money=>console.log(money),error:error=>console.log(error)})moneySubscription.unsubscribe()
Thanks a lot, jsmanifest. Please don't stop these awesome introductions, I never knew about the 2 variations and differences for handling promises. Again Thanks Sir.
Hi there and thanks for your article. I didn't know about the
Promise.allSettledand your article just made me discover this!I think your example:
Is missing its callback:
Thanks for this. One thing I've had issues with in the past is handling different errors when you have a long promise chain hitting different APIs.
In my case, each error needed to be handled differently, and the promise chain needs to be stopped if something fails. I couldn't use Promise.all in this case since promise2 relied on promise1 and promise3 relied on promise2.
How would you handle this case?
Hi Will.
You can catch errors when chaining promise in a single
catch.As you can see, I'm only using one
catch, and it will catch any error thrown in any branch of the chain. Try removing a character from one of the URLs to trigger an error and see the output.You could even use
async/awaitkeywords to modelize your problem in a more procedural form.Thanks for the reply. I knew about the single catch, but I was wondering for a more complex example what people would do. Say instead of hitting the same API server for each call, you are hitting different ones, each with their own error responses.
I guess you could have a single catch, and have a unique handler for each error type, but I found this was not as clean as I liked.
My solution to handle a scenario like this was storing an any errors caught mid promise chain in a variable and handling that error in a more procedural manner. I updated your example with how I would do it. Using async/await makes this way of handling errors cleaner than doing everything in the catch block imo.
I understand what you are trying to do. You could use custom Error subclasses which allow you to keep handling errors in the catch part while still having some control over which kind of error is thrown instead of a generic one.
Beautiful 😍
Thanks a lot, jsmanifest. Please don't stop these awesome introductions, I never knew about the 2 variations and differences for handling promises. Again Thanks Sir.
Haha I think I'm gonna append this articles (as a more comprehensive and in-depth source) to the top of one of my articles about a similar thing.
Great article. One question: What's the difference between async-await and promise other than async-await being syntactical sugar?
One thing that trips up people for async await is the return from an async function is always a Promise, whether you return something or not.