I am reading about error handling, and the book says
If a throw occurs inside a Promises then handler function, then it is
a rejection. One way to think about exceptions and rejections is that exceptions are synchronous errors and rejections are asynchronous errors.
Questions
The book writes rejection, but shouldn't that be unfulfilled?
I were under the impression that a throw is always an exception?
And why are exceptions only for synchronous code?
An unfulfilled Promise is simply one that hasn't been fulfilled, which is quite possible even if it doesn't reject. For example:
const prom = new Promise((resolve) => {
// code here that never calls `resolve`
});
That is a Promise that will never be fulfilled - but it won't reject either.
An "unfulfilled" Promise may not necessarily hang forever like the above - it's simply a Promise that hasn't resolved yet.
a throw is always an exception?
To an extent, yes, though it behaves somewhat differently when inside a Promise - it won't cause an error event. Instead, it'll try to find a .catch handler in the Promise chain it's currently in, and if it doesn't find one, an unhandledrejection event will be fired.
And why are exceptions only for synchronous code?
That's just how the language was designed.
I think you need to understand the reason why rejections are needed, the problem it tries to solve. Consider a simple example such as this:
try {
iDoNotExist
} catch(e) {
//e ReferenceError
}
Pretty simple, the code is being evaluated and "tried" for errors. There's such an error and well, it gets caught.
Now, what if we changed it a little bit into this:
try {
setTimeout(function(){ iDoNotExist }, 1000);
} catch(e) {
//e ReferenceError
}
If you run this code, you'll notice that your javascript environment will emit an Error. It's not being caught here. Why? Because the code that throws the error is not being run when it's being "tried", only the setTimeout function which simply schedules the function and well, that function is doing it's job, it's scheduling it correctly. This in turn is the same reason why so many people get it wrong when they try accessing a value that's product of an async function. E.g.
let result;
setTimeout(() => result = true, 1000);
console.log(result) // Why is this undefined? - Famous last question
Enter promises to the rescue, which not only allow you to recover a value which you would typically return, it also lets you recover any potential error that happens on said async operations. Providing you with semantics that are similar with synchronous code (even more when paired with async functions).
So, I would say rejections are complementary to exceptions. To preserve your program flow when there's an asynchronous boundary (just like fulfilled promises do to preserve function composition).
As for what you would call unfulfilled well... there's a couple of things. unfulfilled means "not fulfilled". A rejected promise IS, technically, an unfulfilled promise. However, an unresolved promise (a promise in a pending state) is ALSO an unfulfilled promise. Technically.
Most people will think of the latter but really it could be either. Mostly because it comes from a time where "fulfill" and "resolve" where used interchangeably (which is wrong). But also because that's typically the expected result of a promise resolution.
Under no circumstance is an unresolved promise a rejected promise. An unresolved promise is in a transitory state in which it could transit into either a fulfilled promise or a rejected one.
Related
I want to make a whatapp bot brainly nodejs. And I want to add an argument. my code is like this:
case 'brainly':
const args = process.argv
brainly(args).then(res => {
for(var i=0; i<res.length; i++){
var jawab = res[i].jawaban
client.sendText(from, jawab[0].text)
}
})
break
But, when I run it shows an error like this:
(node:7960) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch().
how to fix this? Please help me.
This means that somewhere in an asynchronous context, most likely inside of the promise created by calling brainly(args), an error occurred, and it wasn't caught and dealt with.
To get started with asynchronous Javascript, I recommend finding some articles about Javascript Promises and Async Functions (that implicitly generate promises, and allow for the await syntax).
There's no real easy way to explain. Javascript is a single-threaded language, but it offers great concurrency through the use of callbacks, promises and the async/await syntax (they all sort of originate from callbacks). Anything that does not happen instantaneously, such as network/disk operations, is asynchronous and must be handled in an appropriate manner. This can be confusing for newcomers as it breaks up the linear asyncronous flow of execution.
Promises are objects that can be created that will either resolve or reject in the future. By calling .then on the promise, you are giving it a callback function that will be called with the resolved value, when it eventually arrives. You should also add a .catch(err => { ... }) handler to the end to deal with errors, which is probably being thrown for some reason as a result of your passed arguments.
I'm currently reading "YKDJS - Async & Performance" by Kyle Simpson, in particular Chapter 3 - Promises.
The author says that any Promise for which no rejection handler is registered receives a default one:
let p = new Promise(function(resolve, reject) { resolve("Yay!"); });
p.then(
function(val) { /* Do whatever */ }
/* Default rejection handler
, function(e) { throw e; } */
);
Later in the chapter he claims that one problem with the way Promises are designed is the following:
In any Promise chain, any error that happens in one of the handler functions of the last Promise in the chain is just "swallowed" instead of being reported.
He proposes to change the way Promises work so that any Promise that doesn't have a rejection handler reports the error by throwing a global error. Then he proposes a theoretical Promise#defer() function one could use on a Promise to prevent this reporting behavior.
Now my question is: How do these two go together? It's true that any Promisethat doesn't have a rejection handler receives a default one which just throws the rejection value as a global error:
Promise.reject("Oops");
/* VM668:1 Uncaught (in promise) Oops */
So already Promises seem to work in just the way he proposes.
Am I misunderstanding something? Thanks for any help.
The Uncaught Handling he mentions in
Some Promise libraries have added methods for registering something
like a "global unhandled rejection" handler, which would be called
instead of a globally thrown error. But their solution for how to
identify an error as "uncaught" is to have an arbitrary-length timer,
say 3 seconds, running from time of rejection. If a Promise is
rejected but no error handler is registered before the timer fires,
then it's assumed that you won't ever be registering a handler, so
it's "uncaught."
In practice, this has worked well for many libraries, as most usage
patterns don't typically call for significant delay between Promise
rejection and observation of that rejection.
has been standardised as unhandled rejection warnings (not using an arbitrary timer, but firing right away). It does indeed work quite well.
He also states in Chapter 4 of ES6 & Beyond
[When] we are not listening for that rejection, […] it will be
silently held onto for future observation. If you never observe it by
calling a then(..) or catch(..), then it will go unhandled. Some
browser developer consoles may detect these unhandled rejections and
report them, but this is not reliably guaranteed; you should always
observe promise rejections.
I noticed something very strange happening when an exception is thrown inside a chain of promises in Parse for React Native. The promise chain never resolves, and never rejects, and the exception is never thrown. It just disappears silently.
Here's sample code to recreate the problem:
// Replacing this with Promise.resolve() prints the error.
// Removing this stage prints the error.
Parse.Promise.as()
// Removing this stage causes a red screen error.
.then(function() {
// Replacing this with Parse.Promise.as() causes a red screen error.
return Promise.resolve();
})
.then(function () {
throw new Error("There was a failure");
})
.then(function () { console.log("Success")}, function (err) { console.log(err) });
As you can see from the comments, it only seems to happen in this particular sequence of events. Removing a stage, or swapping a Parse promise for a native JS promise, causes things to behave again. (In my actual code, the "Promise.resolve()" stage is actually a call into a native iOS method that returns a promise.)
I'm aware that Parse promises don't behave exactly like A+ compliant promises (cf. https://stackoverflow.com/a/31223217/2397068). Indeed, calling Parse.Promise.enableAPlusCompliant() before this section of code causes the exception to be caught and printed. But I thought that Parse promises and native JS promises could be used together safely.
Why is this exception disappearing silently?
Thank you.
Why is this exception disappearing?
Parse does by default not catch exceptions, and promises do swallow them.
Parse is not 100% Promises/A+ compatible, but nonetheless it does try to assimilate thenables that are returned from then callbacks. And it does neither catch exceptions nor executes its own callbacks asynchronously.
What you are doing can be reproduced without then using
var p1 = new Parse.Promise();
var p2 = new Parse.Promise();
// p2 should eventually settle and call these:
p2._resolvedCallbacks = [function (res) { console.log("Success") }];
p2._rejectedCallbacks = [function (err) { console.log(err) }];
function handler() {
throw new Error("There was a failure");
}
// this is what the second `then` call sets up (much simplified):
p1._resolvedCallbacks = [function(result) {
p2.resolve(handler(result)); // throws - oops
}];
// the native promise:
var p = Promise.resolve();
// what happens when a callback result is assimilated:
if (isThenable(p))
p.then(function(result) {
p1.resolve(result);
});
The problem is that p1.resolve is synchronous, and executes the callbacks on p1 immediately - which in turn does throw. By throwing before p2.resolve can be called, p2 will stay forever pending. The exceptions bubbles up and becomes the completion of p1.resolve() - which now throws in a callback to a native then method. The native promise implementation catches the exception and rejects the promise returned by then with it, which is however ignored everywhere.
silently?
If your "native" promise implementation supports unhandled rejection warnings, you should be able to see the exception hanging around in the rejected promise.
For your consideration in addition to technical reasons provided in your quoted answer:
Compliant promises
ES6/A+ compliant Promise instances share:
When a promise is settled, its settled state and value are immutable.
A promise cannot be fulfilled with a promise.
A then registered 'fulfill' listener is never called with a promise (or other thenable) object as argument.
Listeners registered by then are executed asynchronously in their own thread after the code which caused them to be executed has run to completion.
Irrespective of whether a listener was registered for call back whan a promise becomes settled ( 'fulfilled' or 'rejected'),
the return value of a listener is used to fulfill resolve the promise returned by its then registration
a value thrown (using throw) by a listener is used to reject the promise returned by then registration, and
A promise resolved with a Promise instance synchronizes itself with the eventual settled state and value of the promise provided as argument. (In the ES6 standard this is described as "locked in").
A promise resolved with a thenable object which is not a Promise instance will skip synch as required: if at first resolved with a thenable which "fulfills" itself with a thenable, the Promise promise will re-synchronize itself with the most recent 'thenable' provided. Skipping to a new thenable to synchronize with cannot occur with A+ promises because they never call a "fulfilled" listener with a thenable object.
Non Compliant promises
Potential characteristics of non compliant promise like objects include
allowing the settled state of a promise to be changed,
calling a then 'fulfilled' listener with a promise argument,
calling a then listener, either for 'fulfilled' or 'rejected' states, synchronously from code which resolves or rejects a promise,
not rejecting a then returned promise after a listener registered in the then call throws an exception.
Interoperability
Promise.resolve can be used to settle its returned promise with a static value, perhaps mainly used in testing. Its chief purpose, however, is to quarantine side effects of non compliant promises. A promise returned by Promise.resolve( thenable) will exhibit all of behaviours 1-7 above, and none of the non compliant behaviours.
IMHO I would suggest only using non A+ promise objects in the environment and in accordance with documentation for the library which created them. A non compliant thenable can be used to to resolve an A+ promise directly (which is what Promise.resolve does), but for full predictability of behaviour it should be wrapped in a Promise object using Promise.resolve( thenable) before any other use.
Note I tried to test Parse promises for A+ compliance but it does not seem to provide a constructor. This makes claims of "almost" or "fully" A+ compliance difficult to quantify. Thanks to zangw for pointing out the possibility of returning a rejected promise form a listener as an alternative to throwing an exception.
I have a function which returns a Promise.
Now, sometimes it makes sense for the consumer to use the "then" function on that Promise. But sometimes the consumer simply does not care about when the Promise resolves, and also not about the result - in other words the same function should also be able to be called in a "fire and forget" manner.
So I want these two usage scenarios:
func().then( ... ); // process Promise
func(); // "fire and forget"
This apparently works, but I wonder if this is considered "bad practice", and in particular if this usage pattern could have any unwanted side effects, ie. leading to memory leaks? Right now I am using bluebird, but I consider to switch to native Promises if that makes any difference.
Remember that every call to then results in a new promise. So any Promise implementation that had a memory leak as a result of a promise not having any resolution handlers attached would be a broken implementation, what with all those promises that we never hook handlers to being returned. I very much doubt implementations of ES2015's promises, Bluebird, Q, etc. have that behavior.
Separately, as conceptually a promise's resolution handlers are basically just functions stored by the promise and then called when appropriate, it's not likely to be a memory leak if you never give it any functions to store.
But, there is a problem with your fire-and-forget, just not a memory leak problem: It breaks one of the main Promise rules: Either handle rejection, or return the promise chain to something else that will handle rejection. Since you're not doing that, if the operation fails, you'll have an unhandled rejection. Unhandled rejections are reported to the console and in some environments may terminate your app (at some point, Node.js may start terminating the process when this happens, see this open issue).
If the fact that then returns a new promise is a surprise, consider:
let p1 = new Promise(resolve => {
setTimeout(() => {
resolve('a');
}, 100);
});
let p2 = p1.then(result => {
console.log("p1.then got " + result);
return 'b';
});
p2.then(result => {
console.log("p2.then got " + result);
});
which outputs
p1.then got a
p2.then got b
WebDriverJS and Protractor itself are entirely based on the concept of promises:
WebDriverJS (and thus, Protractor) APIs are entirely asynchronous. All
functions return promises.
WebDriverJS maintains a queue of pending promises, called the control
flow, to keep execution organized.
And, according to the definition:
A promise is an object that represents a value, or the eventual
computation of a value. Every promise starts in a pending state and
may either be successfully resolved with a value or it may be rejected
to designate an error.
The last part about the promise rejection is something I don't entirely understand and haven't dealt with in Protractor. A common pattern we've seen and written is using then() and providing a function for a successfully resolved promise:
element(by.css("#myid")).getAttribute("value").then(function (value) {
// do smth with the value
});
The Question:
Is it possible that a promise returned by any of the Protractor/WebDriverJS functions would not be successfully resolved and would be rejected? Should we actually worry about it and handle it?
I've experienced a use-case of promise rejection while using browser.wait(). Here is an example:
var EC = protractor.ExpectedConditions;
function isElementVisible() {
var el = element(by.css('#myel'));
// return promise
return browser.wait(EC.visibilityOf(el), 1000)
.then(function success() {
return true; // return if promise resolved
}, function fail() {
return false; // return if promise rejected
});
}
expect(isElementVisible()).toBe(true);
expect(isElementVisible()).toBe(false);
Here, if element is on a page, success will be executed, otherwise, if it is not found when 1 second passes, then fail will be called. My first point is that providing a callback for rejection gives an ability to be consistent with what one should expect. In this case I am kinda sure that promise will always resolve to true or false, so I can build a suite relying on it. If I do not provide a fail callback, then I'll get an Uncaught exception because of timeout, which will still fail my particular spec and still run the rest of the specs. It won't be uncaught by the way, Protractor is gonna catch it, but here I want to bring a second point, that Protractor is considered a tool which you use to write and run your code, and if an exception is caught by Protractor, then this exception has left your code unhandled and your code has a leak. But ... at the same time I do not think that one should waste time to catch everything in tests: if there is no element on a page or click has failed, then a respective spec will obviously fail too, which is fine in most of the cases. Unless you want to use the result of failure to build some code on top of it like it is in my sample.
That is the great thing about promises you are going to get a response, either an response of data or an error message. That extended to a series of promises like Webdriver uses you are going to get an array of responses or a failure response of the first one that fails. How you handle the failed response is up to you I usually just dump it into a log for the console to see what failed. The only thing you need to figure out is do you abort the rest of your tests or do you continue on.
Here is a decent article on the subject as well. http://www.toolsqa.com/selenium-webdriver/exception-handling-selenium-webdriver/
Fyi what you are doing is fine you are just never bothering to catch any of the errors though, I am not sure if that matters to you or not, you could also abstract the call in a function to auto handle the errors for you if you wanted to log them somewhere.