How do you escape try/catch hell in Javascript? - javascript

Ok, I like(d) try/catch with await/async.
But what do I do with this.
I wanted to do this..
let a = await doAbc();
let b = await do123(a);
what it becomes instead is
let a, b;
try {
a = await doAbc();
} catch(e) {
a = await doZxc();
}
try {
b = await do123(a);
} catch (e) {
console.log(e);
return;
}
if (b.data == undefined) {
return -1;
} else {
return b;
}
At this point I'm regretting everything.

Remember that you can await any promise. So you could do:
let a = await doAbc().catch(doZxc); // or .catch(() => doZxc())
let b = await do123(a);
Or even
let b = await doAbc().catch(doZxc).then(do123);
Together with the rest of your code:
try {
let b = await doAbc().catch(doZxc).then(do123);
return b.data == undefined ? -1 : b;
} catch (e) {
console.log(e);
return;
}

If it's all in one logical function, you can group all your await in one try and then take action based on error.
let a
let b
try {
a = await doAbc();
b = await do123(a);
} catch (err) {
// take appropriate action based on err
}

Create to function first return a and second using first function returned value to create b , somthing like this code
function firstCode(){
try {
a = await doAbc();
} catch(e) {
a = await doZxc();
}
return a;
}
function secondFunction(){
try {
b = await do123(firstFunction());
} catch (e) {
console.log(e);
return;
}
}

Related

How to refactor "if x return x" statements

I am looking for a way to refactoring this "if x return x" pattern. It seems to be redundant.
For example:
async exampleFunction(a) {
const firstResult = await this.firstHandler(a);
if (firstResult) {
return firstResult;
}
const secondResult = await this.secondHandler(a);
if (secondResult ) {
return secondResult;
}
const thirdResult = await this.thirdHandler(a);
if (thirdResult) {
return thirdResult;
}
}
function exampleFunction(a) {
return this.firstHandler(a) || this.secondHandler(a);
}

Check image url using javascript async/await

I've seen multiple questions like this here but all of them just use alert or console.log as the result and I have a different problem.
I'm trying to verify if an image url is valid using async/await and axios.
async function checkImageUrl(imageUrl) {
let result = false;
const promise = await axios.get(imageUrl);
promise.then(() => {
console.log('result TRUE');
result = true;
}).catch(() => {
console.log('result false');
result = false;
});
console.log(result);
return result;
}
the image urls are in a json array. I use this in another function like this:
let imageValid = false;
someJson.some((obj) => {
if (obj?.image != null) {
imageValid = checkImageUrl(obj.image);
console.log(imageValid);
if (!imageValid) return true;
}
return false;
});
if (!imageValid) {
return;
}
I've used some console.logs to check the results. The problem is I never see those logs in async function and console.log(imageValid) always prints a Promise object in console. Is can't figure out how to implement this the right way.
You cant use async-await in some function. You can use tradition for-loop. Same time you can clean up the checkImageUrl function
function checkImageUrl(imageUrl) {
return axios
.get(imageUrl)
.then((x) => true)
.catch((x) => false);
}
async function main() {
let imageValid = false;
for (let index = 0; index < someJson.length; index++) {
const obj = someJson[index];
if (obj?.image != null) {
imageValid = await checkImageUrl(obj.image);
if (imageValid) {
break;
}
}
}
if (!imageValid) {
return;
}
}
main();
This is my solution:
async function checkImageUrl(imageUrl) {
let result = false;
try {
const res = await axios.get(imageUrl);
result = true;
} catch (err) {
console.log(err);
}
console.log("result", result);
return result;
}
(async () => {
let imageValid = false;
someJson.some((obj) => {
if (obj?.image != null) {
imageValid = await checkImageUrl(obj.image);
console.log(imageValid);
if (!imageValid) return true;
}
return false;
});
if (!imageValid) {
return;
}
})();

How to do async process for multiple functions with loops in each functions

I have four functions in which each function has a loop inside it. Based on the completion of the first function loop the second function should be called and completion of second functions loop should call the third function.
I have used async and await but it didn't work.
Can anyone tell me what is wrong in my code?
First Function:
selectedUser = (userName, userId) => {
this.isFilterByNameSelected = true;
this.props.dispatch(fetchDuesChitties()).then((datas) => {
Object.keys(datas).map((key) => {
if (datas[key].chittieUsers) {
let chittieUsers = datas[key].chittieUsers;
Object.keys(chittieUsers).map((userKey) => {
if (chittieUsers[userKey].userId === userId) {
this.userTicketNumber[key] = {
name: userName,
chitId: datas[key].chitId,
chittieId: key,
chitName: datas[key].chitName,
chittieName: datas[key].chittyName,
auctionsCompleted: datas[key].auctionsCompleted,
userId: userKey
};
}
});
}
});
this.getChittiePayment();
});
};
Second Function:
getChittiePayment = () => {
Object.keys(this.userTicketNumber).map((key) => {
let totalAmount = 0;
let auctionsCompleted = this.userTicketNumber[key].auctionsCompleted;
let chitId = this.userTicketNumber[key].chitId;
let paymentDetails = this.props.chits[chitId].paymentDetails;
for (var i = 0; i < auctionsCompleted; i++) {
totalAmount += parseInt(paymentDetails[i].dueAmount);
}
this.userTicketNumber[key].totalAmount = totalAmount;
});
this.getUsersDuePayment();
}
Third Function:
getUsersDuePayment = () => {
Object.keys(this.userTicketNumber).map((key) => {
let customerId = this.userTicketNumber[key].userId;
let auctionsCompleted = this.userTicketNumber[key].auctionsCompleted;
this.props.dispatch(fetchPaymentsByUserId(customerId, auctionsCompleted)).then((payments) => {
this.userTicketNumber[key].amountPaid = payments;
});
});
this.getBalanceAmount();
}
Fourth Function:
getBalanceAmount = () => {
Object.keys(this.userTicketNumber).map((key) => {
let userKey = this.userTicketNumber[key];
if (userKey.totalAmount && userKey.amountPaid) {
let balanceAmount = userKey.totalAmount - userKey.amountPaid;
this.userTicketNumber[key].pendingAmount = balanceAmount;
}
});
this.setState({ userFilter: this.userTicketNumber });
}
You have to return a promise from second and third function in order to get this work. Try below example. Hope this will help you.
async function First(){
console.log('Firts Func started');
await Second();
console.log('End');
}
function Second(){
return new Promise(async (resolve,reject)=>{
console.log('At Second Function');
await Third();
console.log('Second func end');
resolve('Data From Second function');
});
}
function Third(){
return new Promise(async (resolve,reject)=>{
console.log('At Third Function');
await Fourth();
console.log('Thidr func end');
resolve('Data From Third function');
});
}
function Fourth(){
return new Promise((resolve,reject)=>{
console.log('At Fourth Function');
console.log('Fourth func end');
resolve('Data From Fourth function');
});
}
First();

Promise return in while loop in node.js

I am new to node.js programming .
I am confused how the async and await works
const async = require('async');
createUser: async (user, myid) => {
let dotill = false;
let userid = null;
const getreturn = async.whilst(
function testCondition() { return dotill === false;},
async function increaseCounter(callback) {
let sr = "AB" + Math.floor(Math.random() * 99999999999) + 10000000000;
userid = sr.substr(0, 9);
await knex.raw('select * from userprofile where user_id=?', [userid]).then((res) => {
console.log(res.rowCount);
if (res.rowCount === 0) {
dotill = true;
callback;
}else{
callback;
}
});
},
function callback(err, n) {
if (err) {
return;
}
return {"done":true, "userid":userid}
}
);
console.log(getreturn);
// getreturn always undefined iam not getting and return
}
getreturn is always undefined how i will be able to return in above code or any other way to working in promise..
async/await is syntactic sugar for functions that chain promises. Do not confuse it with the callback-based async.js library, and don't use the latter when working with promises - they don't work together. Instead of trying to call async.whilst with more or less appropriate callbacks, just use a plain simple while loop:
// const async = require('async'); // remove this!
async createUser(user, myid) {
let dotill = false;
let userid = null;
while (!dotill) {
const sr = "AB" + Math.floor(Math.random() * 99999999999) + 10000000000;
userid = sr.substr(0, 9);
const res = await knex.raw('select * from userprofile where user_id=?', [userid]);
console.log(res.rowCount);
if (res.rowCount === 0) {
dotill = true;
}
}
return {"done":true, "userid":userid};
}
(also you can simplify this to a while (true) { …; if (…) return } loop without that dotill variable)

Chaining Promises Cross Function Javascript

I suspect I've fundementally misunderstood Javascript promises, any ideas?
I have a pretty function that queries a database containing music that looks like this:
function searchDatabaseForTrack(query,loadedResults){
loadedResults = loadedResults || [];
desiredResults = 100;
if (loadedResults.length < desiredResults) {
try {
databaseApi.searchTracks(query, {"offset":loadedResults.length, "limit":"50", }).then(function(data){
i=0
if (data.tracks.items.length == 0) {
console.log(`Already loaded all ${loadedResults.length} tracks!`)
console.log(loadedResults)
return loadedResults;
}
else {
for (thing in data.tracks.items){
loadedResults.push(data.tracks.items[i]);
i=i+1;
}
console.log(loadedResults.length, " tracks collected");
searchDatabaseForTrack(query,loadedResults)
}
});
} catch(err) {
console.log("ERROR!", err)
console.log(loadedResults)
return loadedResults;
}
} else {
console.log(loadedResults)
return loadedResults;
}
}
And then a bit later, I try to call and use the data retrieved.
function getArtistTracks(artistName){
searchDatabaseForTrack(artistName).then(function(data){
console.log(songs);
songs.sort(function(a,b){
var c = new Date(a.track.album.release_date);
var d = new Date(b.track.album.release_date);
return d-c;
});
console.log("songs", songs);
var newsongs=[];
i=0
for (song in songs) {
newsongs.push(songs[i].track.uri);
i++
};
return newsongs;
});
}
What I'm trying to do is get the second function "getArtistTracks" to wait for the completion of the query in the first function. Now I could just call the databaseApi.searchTracks directly, but there's a limit of 50 tracks returned per result — which kind of screws me over.
searchDatabaseForTrack().then(...) shouldn't work since searchDatabaseForTrack() doesn't return a promise, so you can either return a promise or use an async function.
instead of a recursive function, you could simply call databaseApi in a for loop,
the desiredResult should be an argument and not hardcoded in the function,
async function searchDatabaseForTrack(query, desiredResults){
let loadedResults = [], data, currOffset = 0;
const iterations = Math.ceil(desiredResults / 50);
for(let n = 0 ; n < iterations; n++){
cuurOffset = n * 50;
data = await databaseApi.searchTracks(query, {"offset":currOffset, "limit":"50", });
if (data.tracks.items.length == 0) {
console.log(`Already loaded all ${loadedResults.length} tracks!`)
console.log(loadedResults)
return loadedResults;
}
else {
loadedResults = loadedResults.concat(data.tracks.items);
console.log(loadedResults.length, " tracks collected");
}
}
return loadedResults;
}
the rest should be fine as long as you add .catch() to handle errors ( as mentionned in previous answer ) which are thrown automatically without the need of the try/catch block :
function getArtistTracks(artistName, 100){
searchDatabaseForTrack(artistName).then((songs) => {
// your previous code
})
.catch((err) => {
// handle error
});
});
Have searchDatabaseForTrack use Promise.all to return the loadedResults after all results have been gotten. Also, make sure not to implicitly create global variables as you're doing with thing. For example, try something like this:
async function searchDatabaseForTrack(query) {
const desiredResults = 100;
const trackPromises = Array.from(
({ length: Math.ceil(desiredResults / 50) }),
(_, i) => {
const offset = i * 50;
return databaseApi.searchTracks(query, { offset, limit: 50 });
}
);
const itemChunks = await Promise.all(trackPromises);
const loadedResults = itemChunks.reduce((a, { tracks: { items }}) => (
[...a, ...items]
), []);
return loadedResults;
};
and
searchDatabaseForTrack(artistName).then((loadedResults) => {
// do stuff with loadedResults
})
.catch((err) => {
console.log("ERROR!", err)
// handle error
});

Categories

Resources