Using promisified request module, i want to get the body attribute of the response. Not sure if I should use a Promise try.
So which one is correct here ?
A. Without Promise.try
request.getAsync("http://example.com")
.then( x => x.body )
.tap( x=> console.log('body:',x) )
B. With Promise.try
request.getAsync("http://example.com")
.then( x => Promise.try( () => x.body ) )
.tap( x=> console.log('body:',x) )
After the first element of a promise chain, an error is guaranteed to throw down the chain's error path and become available to be caught by a .then(null, errorHandler) or .catch(errorHandler).
Therefore there is no point using Bluebird's Promise.try() other than to get a chain reliably started. Doing so will just bulk up your code and make it less efficient.
How about inner chains?
This is more interesting. Inner chains are commonly used to allow access to earlier results via closure. Flattened chains lose this ability.
Consider :
request.getAsync("http://example.com")
.then( x => {
return untrusted.method().then((y) => other.method(x, y));
});
The inner chain has its own starter, untrusted.method(), which may cause failure in one of two ways:
it may throw.
it may return a non-thenable.
A throw is unavoidable (without addressing untrusted.method()), though the thrown error will be catchable in the outer chain.
But a non-thenable can be guarded against. You can write :
request.getAsync("http://example.com")
.then(x => {
return Promise.try(untrusted.method).then((y) => other.method(x, y) );
});
Now Promise.try() ensures the inner chain has a reliable start. Promise.try(untrusted.method) is guaranteed to be thenable.
As a bonus, an error thrown by untrusted.method() is now catchable in the outer chain or the inner chain, which can be useful, particularly for error recovery.
Promise.resolve(untrusted.method()) would similarly protect against a non-thenable being returned but would not allow a synchronous throw to be caught within the inner chain.
DEMO: untrusted() throws
DEMO: untrusted() returns value, not promise.
So in summary,
within a promise chain, there's no value in wrapping synchronous expression(s) in Promise.try().
within a promise chain , there's no value in wrapping trusted, asynchronous function/method calls in Promise.try().
within a promise chain, there is potentially great value in wrapping an untrusted function/method call in Promise.try() to guarantee an inner chain's reliable start.
Not sure if I should use a Promise.try.
No, you should not. In a promise then callback, all synchronous exceptions will be caught and lead to a rejection of the result promise, there is nothing you need to do for that. No try/catch statements, no Promise.try invocations. They would just be unnecessary fluff.
Promise.try should only be used at the start of a promise chain, where you are not yet in a promise callback.
The definition of this Promise.try is:
Start the chain of promises with Promise.try. Any synchronous
exceptions will be turned into rejections on the returned promise.
So it depends by the implementation of request.getAsync method. Does it throw any exception?
If the answer is "no", you do not need to use Promise.try.
If the answer is "yes", you can use Promise.try if you need to catch the error thrown by request.getAsync as rejected promise. In this case, you can wrap the
request.getAsync inside Promise.try:
Promise.try(() => {
return request.getAsync("http://example.com");
}).tap(x => console.log('body:', x.nody));
Please note that if the answer is "yes" but do not want to catch the exception as a rejected promise, you do not need to use Promise.try.
Related
When working with promises in JavaScript, we have a possibility to use .then, .catch and .finally. Each of these methods returns a new Promise object.
Using .then is pretty straightforward - we chain them. The use case for finally - is to put it at the end of the chain of .then and .catch. But
In the code below, as I understand, we initialize promise p which can resolve or reject. I could use .then(resolutionHandler, rejectionHandler), which would be self-explanatory as it's only 1 .then "handler" with both handlers, but in case of sequencing .then and .catch instead of the latter approach-
**Are .then and .catch handlers somehow paired and treated like .then(resolutionHandler, rejectionHandler)? or something else is happening? **
const p = new Promise((resolve, reject) => {
reject("ups...");
});
p
.then(data => {
// this is success handler for Promise "p"
})
.catch(err => {
// Is this failure handler for Promise "p"?
})
Not exactly. When you have p.then(handleThen).catch(handleCatch), if p rejects, handleCatch will handle it. But handleCatch will also handle errors thrown by handleThen.
Although those sorts of errors are pretty unusual with if handleThen contains only synchronous code, if handleThen returns a Promise, handleCatch will be able to handle that Promise if it rejects.
<somePromiseChain>
.catch(handleCatch);
will have the handleCatch handle any errors thrown anywhere in the above Promise chain.
In contrast, with p.then(resolutionHandler, rejectionHandler), the rejectionHandler will only handle a rejection of p. It will completely ignore anything that occurs in resolutionHandler.
If the resolutionHandler is completely synchronous, doesn't return a Promise, and never throws (which is pretty common), then .then(resolutionHandler, rejectionHandler) is indeed equivalent to.then(resolutionHandler).catch(rejectionHandler). But it's usually a good idea to use .then(..).catch(..).
With p.then(success).catch(fail), the .catch is actually attached to the Promise returned by the .then - but if p rejects, the .then's Promise rejects as well, with the same value as p's rejection. It's not that the catch is attached directly to p, but it's attached to a .then which passes p's rejection through.
Every .then / .catch is attached directly to the upper Promise it's called on, but sometimes that upper Promise passes through the value from its upper Promise unaltered. That is. p.then(undefined, fail).then(success) will run success if p resolves, with the intermediate .then passing the resolution through. With rejection, p.then(success).catch(fail) will run fail because the .then(success) passes the failure from p through unaltered.
Calling catch internally calls reject
As per mdn
The catch() method returns a Promise and deals with rejected cases only. It behaves the same as calling Promise.prototype.then(undefined, onRejected) (in fact, calling obj.catch(onRejected) internally calls obj.then(undefined, onRejected)).
I'm learning to convert my Node.js code style from callback to promise which seems to be the tendency and it has many advantages. To prevent the misunderstanding of the important points and benefits of the promise, I'm reading
document on MDN . I can understand Examples in this page, but I am not clear with the note that at the beginning of the document, it had mentioned :
Note: ... If the first argument is omitted or provided a non-function,
the new Promise that is created simply adopts the fulfillment state of
the Promise that then is called on (if it becomes fulfilled). If the
second argument is omitted or provided a non-function, the new Promise that
is created simply adopts the rejection state of the Promise that then is called
on (if it becomes rejected).
Sorry in advance if this is trivial.
Hope for the explanation with examples, thanks.
EDIT: Updated to better match the spec - see here and here.
The .then method calls one of two functions, depending on whether or not the Promise it's attached to has fulfilled or rejected. It then returns a new Promise based on the result of that call. This allows you to run different logic depending on whether or not a Promise was successful, and makes it possible to chain Promises together easily.
If you decide not to pass in one of those functions, however, it uses sensible defaults - which is what the note you posted is alluding to. It's probably a lot easier to demonstrate than to describe, though!
If you leave out the onRejected callback, like so:
myPromise.then(function (value) {
console.log("success!");
});
The result is the same as doing this:
myPromise.then(function (value) {
console.log("success!");
}, function (reason) {
throw reason;
});
If you leave out the onFulfilled callback, like so:
myPromise.then(null, function (reason) {
console.log("fail!");
});
The result is the same as:
myPromise.then(function (value) {
return value; // the same as returning Promise.resolve(value)
}, function (reason) {
console.log("fail!");
});
If you leave both out... it's basically pointless, but still:
myPromise.then();
This is effectively the same thing as:
myPromise.then(function (value) {
return value;
}, function (reason) {
throw reason;
});
Which is in turn, basically just:
myPromise
The other answers provide good explanations, but it might be easier to express this using the concept of skipping over.
If and when the promise fulfills, then the first argument to then is invoked (as long as it is a function); if and when the promise rejects, then the second argument to then is invoked (as long as it is there and is a function). In other cases, the .then is just skipped over.
Purists would object that it is incorrect to say the .then is "skipped over", and that what is really happening is that the .then creates a new promise which is equivalent to (or assumes the state of) the original promise. That's technically correct, but informally it's easier to talk and think about the .then getting "skipped".
Examples:
function log(v) { console.log("value", v); }
function err(e) { console.log("error", e); }
Promise.resolve(1).then(null, err).then(log);
^^^^^^^^^^^^^^^ "SKIPPED" (onFulfilled is null)
Promise.reject(1).then(log).catch(err);
^^^^^^^^^ "SKIPPED" (onRejected is not given)
For completeness, the corresponding behavior for catch is:
If and when the promise rejects, then the argument to catch is invoked (as long as it is a function). In other cases, the .catch is just skipped over.
Promise.resolve(1).catch(err).then(log);
^^^^^^^^^^ "SKIPPED" (promise did not reject)
If you think about it carefully, you will see that this all means that .then(null, handler) is exactly equivalent in every way to .catch(handler). So catch can be thought of as a kind of convenience routine.
But what's the point of allowing, but then ignoring, non-function handlers? Shouldn't they throw a TypeError or something instead? Actually, this is a "feature" which can be used as follows:
promise.then(isWednesday && wednesdayHandler)
If it's Wednesday, then this will evaluate to wednesdayHandler and we can do some special Wednesday processing. It it's not Wednesday, then this will evaluate to false, which is obviously not a function, so the whole then clause will be "skipped".
I don't have too much to add to this that the other answers don't already--just that I came to this question in the process of writing my own question about this, at which point SO miraculously suggested this one as a possible duplicate (when it did not come up in my previous search attempts).
Anyways the current documentation on MDN on the parameters to Promise.prototype.then have changed a bit since the OP and I think are still confusing, if not even moreso than before, so I thought I would add a follow-up answer concerning the current documentation which reads:
onFulfilled Optional
A Function called if the Promise is fulfilled. This function has one argument, the fulfillment value. If it is not a function, it is internally replaced with an "Identity" function (it returns the received argument).
What's confusing about this wording is it's not totally clear what is the antecedent of "received argument". Without already being familiar with the details of the Promises spec, one could read this as the "identity" function returning the argument received by the then() call. I.e. that something like this:
let promise = new Promise((resolve, reject) => resolve("value"));
let chained = promise.then("new value");
is equivalent to this:
let promise = new Promise((resolve, reject) => resolve("value"));
let chained = promise.then(() => "new_value");
so that the value resolved from chained is "new_value".
When in fact, "received value" refers to the resolved value of the original promise that .then() was chained from, i.e.:
let promise = new Promise((resolve, reject) => resolve("value"));
let chained = promise.then(() => "value");
So writing promise.then("not_a_callable") completely ignores "not a callable" and is resolved to the value that fulfilled the original promise, whatever it happens to have been.
Personally, I think this confusing behavior, but it is what it is.
According to MDN:
The executor function is executed immediately by the Promise implementation, passing resolve and reject functions
What were the actual reasons for this decision?
Why promises are not lazy?
What were the actual reasons for this decision?
The revealing Promise constructor with the callback was just an improvement over the older deferred pattern. The callback was never meant to provide choice over the evaluation time, it is supposed to provide a scope with error handling for the resolver functions.
Why promises are not lazy?
Because promises represent the asynchronous result values, nothing more. They're kept simple, without featuring lazyness (and representing the whole computation, with methods to start/repeat/etc). You can trivially get that by using a function that returns a promise instead.
Promises are meant to provide continuations, and actual state of standard Promise object proposes the following pattern:
function doStuff() {
return new Promise((resolve, reject) => { // execution function
// Do stuff here
});
}
I would ask a question myself to understand why Promise's execution function is called immediatelly: where you would do the promised stuff?
Clearly, it's called immediatelly because you're making a promise that some stuff will be successfully or unsucessfully done, and that stuff should start to be processed as soon as you call the enclosing function to avoid confusion to the caller.
The point of a promise is to have something to return from a function that callers can attach their callbacks to rather than pass them in. The constructor is a red herring to answer "why", as it exists solely to wrap old callback-style code in an imperfect world.
All JS functions are synchronous, even those returning a promise (es8's async is syntactic sugar).
The Promise constructor executor function exists to provide unified error handling. Consider:
function foo() {
""(); // throws TypeError
return Promise(resolve => {
""(); // rejects promise with TypeError
});
}
Callers would need both try{ foo().catch(failed); } catch(e) { failed(e); } = Sucks.
So put all your synchronous code inside the executor function to unify errors for your callers. That's what it's for, which I think is your real question.
"Lazy" execution would defeat the purpose of unifying error handling of all your code.
I'm trying to promisify JSON.parse method but unfortunately without any luck. This is my attempt:
Promise.promisify(JSON.parse, JSON)(data).then((result: any) => {...
but I get the following error
Unhandled rejection Error: object
Promise.promisify is thought for asynchronous functions that take a callback function. JSON.parse is no such function, so you cannot use promisify here.
If you want to create a promise-returning function from a function that might throw synchronously, Promise.method is the way to go:
var parseAsync = Promise.method(JSON.parse);
…
parseAsync(data).then(…);
Alternatively, you will just want to use Promise.resolve to start your chain:
Promise.resolve(data).then(JSON.parse).then(…);
Late to the party, but I can totally understand why you might want a promisified JSON parse method which never throws exceptions. If for nothing else, then to remove boilerplate try/catch-handling from your code. Also, I see no reason why synchronous behavior shouldn't be wrapped in promises. So here:
function promisedParseJSON(json) {
return new Promise((resolve, reject) => {
try {
resolve(JSON.parse(json))
} catch (e) {
reject(e)
}
})
}
Usage, e.g:
fetch('/my-json-doc-as-string')
.then(promisedParseJSON)
.then(carryOn)
.catch(dealWithIt)
First of all, JSON.parse is not an asynchronous function. So, don't try to promisify it.
Because I want to create a chain of promises where JSON.parse stand at the top
Then, simply create a Promise resolved with the parsed JSON object, like this
Promise.resolve(JSON.parse(data))
.then(...)
Now, to your actual question, you are getting the error,
Unhandled rejection Error: object
because, if your chain of promises is rejected, you are not handling it. So, don't forget to attach a catch handler, like this
Promise.resolve(JSON.parse(data))
.then(...)
.catch(...)
READ THIS There is a problem with the approach I have shown here, as pointed out by Bergi, in the comments. If the JSON.parse call fails, then the error will be thrown synchronously and you may have to write try...catch around the Promise code. Instead, one would write it as Bergi suggested in his answer, to create a Promise object with just the data, and then do JSON.parse on that Promise chain.
What is the difference between using the Nodejs Q promise library's .finally() and .done() statements.
For example whats the difference between these two?
Q(...)
.then(...)
.finally(); //or fin()
Q(..)
.then()
.done();
promise.done(onSuccess, onError) simply allows you to process resolved value. An additional benefit is that does not imply any error swallowing (as it is the case with promise.then()), it guarantees that any involved exception would be exposed. It also effectively ends the chain and does not return any further promise.
promise.finally(fn) is for registering a task that must be done after a given promise resolves (it doesn't matter whether promise succeeds or fails). Usually, you use it for some kind of cleanup operations e.g. imagine you set up a progress bar, that needs to be hidden after the request is done (no matter if it was successful), then just do promise.finally(hideProgressBar). Additionally promise.finally() returns input promise, so you can return it for further processing.
The difference is in chaining and error handling, and error logging:
Q(...)
.then(...)
.finally();
Here, if the then throws, the finally will still run, but no error will log. In Q finally is run regardless of the .then being successful or not. This is like the finally keyword in JS try/catch/finally. It is also possible to chain additional thens to the chain in this case.
Q(..)
.then()
.done();
Here, done indicates that the promise chain has ended, you can not chain to it any more. If you pass it only an onFulfilled handler it will not run if the then threw, and it will log errors if it ends with an exception.