I'm currently running through, and attempting to familiarize myself with promises, and I will cut through the introductory concepts, and get to the meat of the matter. Within NodeJS, using the library BlueBird. I don't want to defer the function calls, I'd also rather not pollute the code more than needed, even though this is introductory coding to get familiar with the premise, as when more advanced concepts are being attempted, I'll get lost on them. I attempted using 'asyn/await' with a try block, but God was that code messy, and didn't work... More or less guidelines:
- I do not want to use Promise.settle, I still want to exit when a function rejects, I'd just like to stay within the Catch block if an error is raised.
- I don't want to use async/await, yield, or generators in some weird way to stop the flow of the code as this is detrimental to the intended practice.
- If the intended solution to handling this is wrong, please don't just say it's wrong, I understand people's time is valuable, but with limited knowledge of the workings of the language, as much documentation as can be thrown at me, or reasons why I'm wrong are more appreciated than not.
- I've seen implementations of the concept in CoffeeScript, I don't see a viable reason to move to that syntax system at the moment, as most anything I may use the language for in the coming months would be bare Node back-end management.
Promises contain a catch mechanism built in, which works perfectly, if dealing with a standard single Promise.
// Try/Catch style Promises
funcTwo = function(activate) {
return new Promise(function(resolve, reject) {
var tmpFuncTwo;
if (activate === true) {
tmpFuncTwo = "I'm successful"
resolve(tmpFuncTwo)
} else if (activate === false) {
tmpFuncTwo = "I'm a failure.";
reject(tmpFuncTwo)
} else {
tmpFuncTwo = "Oh this is not good."
throw new Error(tmpFuncTwo);
}
});
}
funcTwo(true)
.then(val => {
console.log("1: ", val)
return funcTwo()
})
.catch(e => {
console.log("2: Err ", e.message)
})
The thing that causes me to be somewhat confused is attempting to uphold the same premise with Promise.all, the error is not handled, as the throw pushes directly to the main Controller. The exception that is thrown from this snippet never makes it to the the Catch block.
funcThree = function(val) {
return new Promise(function(resolve, reject) {
if (val > 0)
resolve((val + 1) * 5)
else if (val < 0)
reject(val * 2)
else
throw new Error("No work for 0");
})
}
// Output in Dev Console
/*
Extrending to the catch block handling, This will fail, the exception is thrown, and ignores the catch block. Terminating the program.
*/
Promise.all([funcThree(1), funcThree(0), funcThree(-3)])
.then(function(arr) {
for (var ind = 0; ind < arr.length; ind++) {
console.log(arr)
};
}, function(arr) {
console.log(arr)
})
.catch(function(e) {
console.log("Error")
})
I've attempted a simple work around, but I am somewhat new to the language, and am not sure if this is adhering to "Best Practices", as they have been drilled into my mind from Python guidelines.
// Promise all, exceptionHandling
funcThree = (val) => {
return new Promise(function(resolve, reject) {
if (val > 0)
resolve((val + 1) * 5)
else if (val < 0)
reject(val * 2)
else {
var tmp = new Error("No work for 0");
tmp.type = 'CustomError';
reject(tmp);
}
})
}
/*
This works, and doesn't cause any type of mixup
*/
Promise.all([funcThree(1), funcThree(0), funcThree(-3)])
.then(
arr => {
for (var ind = 0; ind < arr.length; ind++) {
console.log(arr)
};
}, rej => {
if (rej.type == 'CustomError')
throw rej;
console.log(arr)
})
.catch(e => {
console.log("Catching Internal ", e.message)
})
This is using the Native Promise library, as well as bluebird
Is there a way to handle this more natively,
In regards to jfriend00's comment. What i mean to say is that I don't want the exception to be handled by anything but the try-catch block. When I attempt to use the same format as for a normal promise, things align perfectly, and my catch is acknowledged, and the error handled. Since Promise.all can only ever resolve/reject I don't think that there is a clean way of delegating the exception that is thrown from the second call to funcTwo in the second code snippet. More or less I'm not sure if what I've done as a workaround," reject, check if reject passed forward an error, and then throw it if it did", is a good solution or if it will cause some deep problem as code expands.