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.'
})
}