await - catch error - UnhandledPromiseRejectionWarning - es6-promise

I'm getting
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 44): Error: fail
main.js
import { request } from './api'
async getData({ commit, state }, ids ){
try {
var x = await request(ids)
commit('getData', x.data)
} catch ( e ) {
console.log('request failed get',e.code,e.errno)
}
}
api.js
export async function request(type,url,ids){
axios.get('localhost/data')
.then(function (response) {
return Promise.resolve(response.data)
})
.catch(function (e) {
return Promise.reject(new Error('fail'))
})
}
How can I handle the promise rejection? Shouldn't the try catch block catch the error from the await function here?

You are mixing up async/await with promises. In api.js, there is no need to use the async keyword. The async keyword makes it so that anything you return from the function is wrapped in a promise, which you don't need, since axios.get returns a promise already.
Also, you forgot to actually return the promise from Axios, your request function just returns undefined.
Lastly, you don't have to return promises from the then and catch methods, just return a value, or throw an error.
If you rewrite the function like this it should work as expected:
export function request(type,url,ids){
return axios.get('localhost/data')
.then(function (response) {
return response.data
})
.catch(function (e) {
throw new Error('fail')
})
}

Related

try/catch block can't stop ER_DUP_ENTRY error from crashing my appliction

Im adding a duplicate to a mysql table and I want to handle elicited ER_DUP_ENTRY error comming back with a Try/Catch block but its just crashing anyway , is there any possible way to handle error and stop application from crashing using a try/catch block?
async function init() {
try {
connection.query(
'SOME INSERT QUERY',
(err, result, feilds) => {
if (err) throw err
console.log(result);
}
);
} catch (e) {
console.log(e);
}
}
init();
The node mysql-library does not support promises out of the box, which means query does not return a promise which you can await. So you can either wrap the query function in a promise yourself:
async function init() {
try {
const duplicateResult = await new Promise((resolve, reject) => {
connection.query(
'SOME INSERT QUERY',
(err, result, fields) => {
if (err) {
return reject(err);
}
resolve(result);
});
});
} catch (e) {
console.log(e);
}
}
or use util.promisify as Always Learning posted alternatively.
The problem is that connection.query returns undefined right away. Your catch is not involved because the call ends before the work is done and will call your callback function later. An exception that occurs during your callback is too late. You try/catch block has already completed.
You can use promisify to wait on it like this though:
const util = require("util");
function init() {
const queryPromise = util.promisify(connection.query);
return queryPromise('SOME INSERT QUERY')
.catch(e => {
console.log("It failed", e);
});
}
init().then(result => {
if (result) console.log("It worked", result);
else console.log("Aww, it didn't work");
});

Stop another .then() execution in chain of promises

I have programme in nodejs & mysql like below
db.query()
.then(1)
.then(2)
.then(3)
.catch()
I am checking a value from database in then(1) and trying to return response from there.In then(2) , I am executing another code that uses some data from result of then(1) and so on..
My problem: When returning response from then(1), catch() is calling(because then(2) have error, not getting data from then(1)) . So is there any way I can stop further execution in then(1) so that then(2) and catch() couldn't call ?
db.query('query......', [val1, val2])
.then(rslt => { return res.json({ mssg: "Email already exists!", error: "Email already exists!" }) })
.then(user => { return db.query('INSERT INTO ', value, (err, res, flds) => { err ? reject(err) : resolve(res) }) })
.then(user => { return res.json({ mssg: "Success", success: true}) })
.catch( (err) => { console.log(err) })
You can (and should) use an async function, instead of using the lower-level .then() API of the Promise object:
async function doTheThing() {
try {
const result = await db.query('...');
if (result) { // user exists
return res.json({...}); // this will end the entire function
}
const user = await db.query('...');
return res.json({...}); // success
} catch (err) {
console.log(err); // I don't recommend doing this. try/catch should be for recovery
}
}

How can I use async/await instead of a promise (.then)

I'm trying to use async/await in my project instead of .then, but it's throwing me an error
here is my code:
export const registerUser = (userData, history) => async dispatch => {
axios
.post('/api/users/register', userData)
await (res => history.push('/login'))
.catch(err => dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
and this is the error i get back
Unhandled Rejection (TypeError): (intermediate value).catch is not a function
await isn't a function that you replace then() with. It is a keyword that you put before an expression that resolves as a promise. When you use it, you also replace the catch() method with a regular try/catch.
export const registerUser = (userData, history) => async dispatch => {
try {
await axios.post('/api/users/register', userData);
history.push('/login');
} catch (err) {
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};

javascript promise catch confusion [duplicate]

What is the best way to handle this scenario. I am in a controlled environment and I don't want to crash.
var Promise = require('bluebird');
function getPromise(){
return new Promise(function(done, reject){
setTimeout(function(){
throw new Error("AJAJAJA");
}, 500);
});
}
var p = getPromise();
p.then(function(){
console.log("Yay");
}).error(function(e){
console.log("Rejected",e);
}).catch(Error, function(e){
console.log("Error",e);
}).catch(function(e){
console.log("Unknown", e);
});
When throwing from within the setTimeout we will always get:
$ node bluebird.js
c:\blp\rplus\bbcode\scratchboard\bluebird.js:6
throw new Error("AJAJAJA");
^
Error: AJAJAJA
at null._onTimeout (c:\blp\rplus\bbcode\scratchboard\bluebird.js:6:23)
at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
If the throw occurs before the setTimeout then bluebirds catch will pick it up:
var Promise = require('bluebird');
function getPromise(){
return new Promise(function(done, reject){
throw new Error("Oh no!");
setTimeout(function(){
console.log("hihihihi")
}, 500);
});
}
var p = getPromise();
p.then(function(){
console.log("Yay");
}).error(function(e){
console.log("Rejected",e);
}).catch(Error, function(e){
console.log("Error",e);
}).catch(function(e){
console.log("Unknown", e);
});
Results in:
$ node bluebird.js
Error [Error: Oh no!]
Which is great - but how would one handle a rogue async callback of this nature in node or the browser.
Promises are not domains, they will not catch exceptions from asynchronous callbacks. You just can't do that.
Promises do however catch exceptions that are thrown from within a then / catch / Promise constructor callback. So use
function getPromise(){
return new Promise(function(done, reject){
setTimeout(done, 500);
}).then(function() {
console.log("hihihihi");
throw new Error("Oh no!");
});
}
(or just Promise.delay) to get the desired behaviour. Never throw in custom (non-promise) async callbacks, always reject the surrounding promise. Use try-catch if it really needs to be.
After dealing with the same scenario and needs you are describing, i've discovered zone.js , an amazing javascript library , used in multiple frameworks (Angular is one of them), that allows us to handle those scenarios in a very elegant way.
A Zone is an execution context that persists across async tasks. You can think of it as thread-local storage for JavaScript VMs
Using your example code :
import 'zone.js'
function getPromise(){
return new Promise(function(done, reject){
setTimeout(function(){
throw new Error("AJAJAJA");
}, 500);
});
}
Zone.current
.fork({
name: 'your-zone-name',
onHandleError: function(parent, current, target, error) {
// handle the error
console.log(error.message) // --> 'AJAJAJA'
// and return false to prevent it to be re-thrown
return false
}
})
.runGuarded(async () => {
await getPromise()
})
Thank #Bergi. Now i know promise does not catch error in async callback. Here is my 3 examples i have tested.
Note: After call reject, function will continue running.
Example 1: reject, then throw error in promise constructor callback
Example 2: reject, then throw error in setTimeout async callback
Example 3: reject, then return in setTimeout async callback to avoid crashing
// Caught
// only error 1 is sent
// error 2 is reached but not send reject again
new Promise((resolve, reject) => {
reject("error 1"); // Send reject
console.log("Continue"); // Print
throw new Error("error 2"); // Nothing happen
})
.then(() => {})
.catch(err => {
console.log("Error", err);
});
// Uncaught
// error due to throw new Error() in setTimeout async callback
// solution: return after reject
new Promise((resolve, reject) => {
setTimeout(() => {
reject("error 1"); // Send reject
console.log("Continue"); // Print
throw new Error("error 2"); // Did run and cause Uncaught error
}, 0);
})
.then(data => {})
.catch(err => {
console.log("Error", err);
});
// Caught
// Only error 1 is sent
// error 2 cannot be reached but can cause potential uncaught error if err = null
new Promise((resolve, reject) => {
setTimeout(() => {
const err = "error 1";
if (err) {
reject(err); // Send reject
console.log("Continue"); // Did print
return;
}
throw new Error("error 2"); // Potential Uncaught error if err = null
}, 0);
})
.then(data => {})
.catch(err => {
console.log("Error", err);
});

Node mysql error is not being caught by Promise reject

I'm making a simple database call wrapped in a promise, and trying to catch the error and pass it through to the promise reject(), but the reject isn't being handled or bubbled back up by the calling code. The code just stops executing when the mysql call fails.
The error within the mysql callback is:
REJECTING QUERY { Error: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?' at line 1
Here is the database query code:
this.query = function(sql, params) {
return new Promise((resolve, reject) => {
_pool.query(sql, params, function(err, result) {
if (err) {
console.log("REJECTING QUERY", err);
return reject(err);
}
resolve(result);
});
});
}
Here is the calling code:
this.createUser = function(data) {
var query = "INSERT into users SET ?";
return new Promise((resolve, reject) => {
Container.DB.query(query, data)
.then((response) => {
console.log("Resolved", response);
return resolve(response);
},(error) => {
console.log("REJECTION ERROR", error);
return reject('An unknown error occurred and has been reported.');
})
.catch((err) => {
console.log("CAUGHT ERROR", err);
});
});
}
I get to "REJECTING QUERY" within the database query code, but nothing in the calling code is reached (ie. .then, or the error handler, or the .catch handler).
Is it possible to get the mysql error to reach these points in code so I can respond to the user? Am I doing something wrong?
The anti-pattern mentioned by #JaromandaX is forcing you to unnecessarily jump through flaming hoops to accommodate it... and your getting burned.
But, first, you are rejecting to the outer (redundant) promise from the then before the catch so the catch is by-passed. After an error is thrown in a promise chain, the first thenable with a second argument (onRejected) will consume it: so it won't be propagated beyond that. But, anyway, you need to trap the error on the outer promise which you are rejecting.
this.createUser = function (data) {
var query = "INSERT into users SET ?";
return new Promise((resolve, reject) => { // the first 'then' rejects to here
Container.DB.query(query, data) // broken promise: anti-pattern
.then((response) => {
console.log("Resolved", response);
return resolve(response);
}, (error) => {
console.log("REJECTION ERROR", error);//<--the error is consumed here and will
// not go any further on this chain
return reject('An unknown error occurred and has been reported.');
})
.catch((err) => { // this will not be called
console.log("CAUGHT ERROR", err); // because it is the 'onRejected'
// argument of a then
});
})
.catch((err) => { // this will be called and the error will be consumed
console.log("CAUGHT ERROR", err);
return 'An unknown error occurred and has been reported.';
});
;
}
Less worse, you can log and re-throw the error in one catch...
this.createUser = function (data) {
var query = "INSERT into users SET ?";
return new Promise((resolve, reject) => { // this is still redundant
Container.DB.query(query, data) // broken promise: anti-pattern
.then((response) => { // on error, skip this because it has no
console.log("Resolved", response); // 'onRejected' argument
return resolve(response);
})
.catch((err) => { // this will be called and the error
console.log("CAUGHT ERROR", err); // will be consumed
return reject('An unknown error occurred and has been reported.');
});
})
;
}
Better, eliminate the anti-pattern and propagate the message with a throw instead of a reject on the (redundant) promise wrapper...
this.createUser = function (data) {
var query = "INSERT into users SET ?";
return Container.DB.query(query, data)
.then((response) => { // on error, skip this because it has no
console.log("Resolved", response); // 'onRejected' argument
return resolve(response);
})
.catch((err) => { // this will be called and the error
console.log("CAUGHT ERROR", err); // will be consumed so need to re-throw
throw new Error('An unknown error occurred and has been reported.');
});
}
Bearing in mind that a catch is just syntactic sugar for then(undefined, reject) and that, once rejected, a promise is no longer pending, calling it's then method will return undefined 'as soon as possible'. So you can chain another then after the catch if you prefer not to throw...
this.createUser = function (data) {
var query = "INSERT into users SET ?";
return Container.DB.query(query, data)
.then((response) => { // on error, skip this because it has no
console.log("Resolved", response); // 'onRejected' argument
return resolve(response);
})
.catch((err) => { // this will be called and the error
console.log("CAUGHT ERROR", err); // will be consumed. The returned promise
}) // state will be rejected but not pending
// It's then method returns 'undefined' as
// soon as possible
.then(() => 'An unknown error occurred and has been reported.');
}
Taking it one step further, bearing in mind that the value returned by a resolved or rejected promise is the return value of whichever of those is called, you can pass any value you like to the consumer via the return in the catch...
this.createUser = function (data) {
var query = "INSERT into users SET ?";
return Container.DB.query(query, data)
.then((response) => { // on error, skip this because it has no
console.log("Resolved", response); // 'onRejected' argument
return resolve(response);
})
.catch((err) => { // this will be called and the error
console.log("CAUGHT ERROR", err); // will be consumed. The returned promise
// state will be rejected but not pending
// but you can still return any value
return 'An unknown error occurred and has been reported.'
})
}