Passing an error from one async function to another - javascript

I have a convoluted system, which totally works on async/await. What I want is to handle multiple types of errors from an async function in one and only try/catch block. Which means that I call this function from another async function.
But the concept of handling exceptions in a parent async function seems to fail. In the below example what I get - is just a warning about unhandled promise rejection, and the catch block in the parent won't ever get an error. I've tried this also with simply throwing and error, but unsuccessfully either.
const die = (word) => new Promise((resolve, reject) => reject(word));
const live = () => new Promise((resolve, reject) => resolve(true));
const daughterAsync = async () => {
await live();
try {
await die('bye');
} catch (err) {
return Promise.reject(err);
}
try {
await die('have a beatiful time');
} catch (err) {
return Promise.reject(err);
}
await live();
};
const parentAsync = async () => {
try {
daughterAsync();
} catch(err) {
console.log('error catched'); // never happens
console.log(err);
}
};
parentAsync();
I have a feeling that I don't get something about async functions to perform such a stunt

Your daughterAsync(); line only starts the promise running, but it doesn't save the reference to it or wait for it to resolve. You need to await the promise returned by daughterAsync inside of parentAsync's try block in order to catch errors in daughterAsync:
const die = (word) => new Promise((resolve, reject) => reject(word));
const live = () => new Promise((resolve, reject) => resolve(true));
const daughterAsync = async () => {
await live();
try {
await die('bye');
} catch (err) {
return Promise.reject(err);
}
try {
await die('have a beatiful time');
} catch (err) {
return Promise.reject(err);
}
await live();
};
const parentAsync = async () => {
try {
await daughterAsync();
} catch(err) {
console.log('error catched');
console.log(err);
}
};
parentAsync();

Related

How to use map inside try/catch?

I have a sample, kindly have a look, if I am doing it the right way,
export const create = async ({ invitationList, testId }) => {
try {
const promises = invitationList.map(async invitationTo => {
return new Promise(async (resolve, reject) => {
const invitation = await InterviewSchedule({
invitationTo,
testId
}).save();
resolve(invitation);
});
});
Promise.all(promises).then(value => {
console.log(value);
});
} catch (error) {
throw error;
}
};
I am unable to catch the error inside the catch block.
The classic try/catch control flow for errors only works when you await the promises. In your code, you are not awaiting the Promise.all. Try this instead:
export const create = async({
invitationList,
testId
}) => {
try {
const promises = invitationList.map(invitationTo =>
new InterviewSchedule({
invitationTo,
testId
}).save());
const results = await Promise.all(promises);
console.log(results);
} catch (error) {
throw error;
}
};

JavaScript, Promise rejection

I'm trying to create this promise:
const getTocStatus = new Promise((resolve, reject) => {
const userInfo = Auth.currentUserInfo();
resolve(userInfo.attributes['custom:tocStatus']);
reject(new Error('Couldn\'t connect to Cognito'));
});
Then use it like this:
getTocStatus.then((response) => {
if (response === 'pending) { //do sth }
}, error => console.log('Error:', error)
But I'm getting the Error:
[TypeError: undefined is not an object (evaluating 'userInfo.attributes['custom:tocStatus']')]
What is badly coded on the promise and it call?
Lionel's answer is correct (I didn't know what Auth.currentUserInfo was, but there's no need for the Promise constructor since you're already dealing with promises:
const getTocStatus = async () => {
try {
const userInfo = await Auth.currentUserInfo()
return userInfo.attributes['custom:tocStatus']
} catch (e) {
new Error("Couldn't connect to Cognito")
}
}
// or with .then syntax
const getTocStatus = () =>
Auth.currentUserInfo()
.then((userInfo) => userInfo.attributes['custom:tocStatus'])
.catch((e) => { Promise.reject(new Error("Couldn't connect to Cognito")) })
The problem is that Auth.currentUserInfo gives you a promise, not a value, so you need to wait for it to complete before you can return its contents. Mario Vernari is also correct in that your error handling has problems too, but that's not why your code is crashing. This should hopefully fix both problems.
const getTocStatus = new Promise(async (resolve, reject) => {
try {
const userInfo = await Auth.currentUserInfo();
resolve(userInfo.attributes['custom:tocStatus']);
} catch (e) {
reject(new Error('Couldn\'t connect to Cognito'));
}
});
You must discriminate when there's an error and when it's not:
const getTocStatus = new Promise((resolve, reject) => {
try {
const userInfo = Auth.currentUserInfo();
resolve(userInfo.attributes['custom:tocStatus']);
}
catch (err) {
reject(new Error('Couldn\'t connect to Cognito'));
}
});
...or something like that.
Finally I did this, but I will fix my code using this:
const getTocStatus = new Promise((resolve, reject) => {
try {
Auth.currentUserInfo()
.then(response => {
resolve(response.attributes['custom:tocStatus'] || TocStatus.CONFIRMED);
})
.catch(err => console.log(err));
} catch (err) {
reject(new Error('Couldn\'t connect to Cognito'));
}
});
And:
getTocStatus.then((response) => {
console.log('response dentro del error', response);
if (response === 'pending') {
// do sth
}
}, error => console.log(error)

Promise should not be async

Why should a Promise not be async? And how do I have to change this function?
With this I'm handling some files using gridFS and it is working as expected. But now I got the linting error not to use async promises. If I remove async, the function is not working anymore.
export async function getFiles () {
await db.connect()
const Images = db.gfs
return new Promise(async function (resolve, reject) { // <-- linting error
Images
.find()
.toArray((err, files) => {
if (err) reject(Error(err))
else if (!files) reject(Error('Failed to retrieve pending files'))
if (anyCondition) { resolve(something) }
else { resolve(files.filter(file => !file.metadata)) }
})
})
}
This would work with some function modularization:
async function otherGetFiles(){
await db.connect();
return await getFiles (db);
}
export function getFiles (db) {
const Images = db.gfs
return new Promise(async function (resolve, reject) {
Images
.find()
.toArray((err, files) => {
if (err) reject(Error(err))
else if (!files) reject(Error('Failed to retrieve pending files'))
// do some things here...
resolve(files.filter(file => !file.metadata))
})
})
}
Please try this code. This would work without any errors or warnings.
export async function getFiles() {
await db.connect()
const Images = db.gfs
return await new Promise(function (resolve, reject) {
Images
.find()
.toArray((err, files) => {
if (err) reject(Error(err))
else if (!files) reject(Error('Failed to retrieve pending files'))
// do some things here...
resolve(files.filter(file => !file.metadata))
})
})
}

React Native: Rendering text from a function

In my loop I have to get the address of lat and long. I have this function using reverseGeolocation
_getLocationAddress = async location => {
return new Promise((resolve, reject) => {
try {
const { status, data } = await srs.getReverseGeolocation(location);
if (data) {
resolve(data.results[0].formatted_address);
}
} catch (err) {
console.log(err);
reject(err);
}
});
};
I also tried not wrapping into promise and not async it doesn't work it keeps returning a promise object. What I need from there is to return the data result into string. Here's my render
renderNewSR() {
const { delivery_items } = this.state;
return delivery_items.map((prop, key) => {
const location = {
latitude: parseFloat(prop.pickuplat),
longitude: parseFloat(prop.pickuplong)
};
//console.log(location);
const address = "";
this._getLocationAddress(location)
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
.....
What is alternative solution to this. I want the result from google api return as string and can be displayed in render.
You are not declaring arrow function async inside new Promise but you are trying to use await inside that function.
Just add async (resolve, reject) to solve the issue.
Also you don't need to use async in async location as you are not awaiting any promise but returning promise in wrapper function.
_getLocationAddress = async location => {
return new Promise(async (resolve, reject) => {
try {
const { status, data } = await srs.getReverseGeolocation(location);
if (data) {
resolve(data.results[0].formatted_address);
}
} catch (err) {
console.log(err);
reject(err);
}
});
};
Hope that helps!!!

What is the proper way to use Promise.reject with javascript

I have this following piece of code
new Promise((resolve, reject) => {
resolve(apiRequest(data))
reject(console.log('Error'))
}).then(response)
Both methods (resolve and reject) are being fired but I want to call reject only when something goes wrong.
How can I throw an error if something goes wrong on that case?
I checked that but it seems like I can not use an If statement to do that check.
new Promise((resolve, reject) => {
const printResult = apiRequest(data)
console.log(printResult) //Outputs Promise {<pending>}
resolve(printResult) //Then it works
reject(console.log('Error'))
}).then(response)
What would be the correct approach to reject a promise?
The easiest way would be with an if condition. i.e
new Promise((resolve, reject) => {
// do something...
if(somethingGoodHappened) {
resolve(data)
} else {
reject(error)
}
})
But usually when dealing with async requests, the thing you are calling will often be returning a promise, so you can attach the then and catch callbacks there.
apiRequest(data)
.then((result) => {
// all good
})
.catch((err) => {
console.log(err)
})
const mock_api = () => new Promise((res, rej) => {
const number = Math.floor((Math.random() * 100) + 1);
setTimeout(() => {
if (number%2==0) return res('randomly RESOLVED')
return rej('randomly REJECTED')
}, 2000)
})
const async_promise = () => new Promise(async (resolve, reject) => {
try {
const resolvedPromise = await mock_api()
resolve(resolvedPromise)
} catch (e) {
reject(e)
}
})
const classicPromise = () => new Promise((resolve, reject) => {
mock_api()
.then(resolve)
.catch(reject)
})
const makeAsyncRequest = async () => {
try {
const data = await async_promise()
console.log('ASYNC AWAIT RESOLVE', data)
} catch (e) {
console.log('ASYNC AWAIT ERR', e)
}
}
makeAsyncRequest()
classicPromise()
.then(r => console.log('PROMISE CHAIN RESOLVE', r))
.catch(e => console.log('PROMISE CHAIN ERR', e))
Because of you resolve before reject so it cannot run into reject,
You can use:
if (printResult) {
resolve(printResult)
} else {
reject(console.log('Error'))
}
You can catch exceptions and return them as rejected Promises
function asyncFunc() {
try {
doSomethingSync();
return doSomethingAsync()
.then(result => {
ยทยทยท
});
} catch (err) {
return Promise.reject(err);
}
}
Always check for err if there is any err return a promise (example below)
// Return new promise
return new Promise(function(resolve, reject) {
// Do async job
request.get(options, function(err, resp, body) {
if (err) {
reject(err);
} else {
resolve(JSON.parse(body));
}
})
})

Categories

Resources