Resolving promises from ES6 Arrow Functions - javascript

Reading the docs as I understand it in ES6 the meaning of:
foo => someFun(foo);
is equivalent to:
foo => { return someFun(foo); }
I'm returning a new Promise and within that code using arrow functions to invoke the resolve & reject methods, e.g.
return new Promise(function(resolve, reject)
{
someFunThatReturnsAPromise()
.then(data => resolve(data))
.catch(err => reject(err));
});
As such is the code in the then actually,
.then(data => return resolve(data))
If so, does it matter that the result of resolve (of which I'm not sure of the type of value) and should I instead be slightly less terse and write it using {} to prevent the implicit return
.then(data => { resolve(data); })

The resolve function already returns undefined, so it makes absolutely no difference if you implicitly return it with a one-line arrow function or don't return it from a function body at all (since the latter means your function body implicitly returns undefined itself).
Furthermore, since you've wrapped the promise returned by someFunThatReturnsAPromise() in a new promise, there's nothing that handles the return anyway so it wouldn't make any difference even if did return something.
More importantly, the way you've wrapped a promise in a new promise is an anti-pattern. The new Promise() construct is only for dealing with asynchronous processes that aren't already promise based.
Since someFunThatReturnsAPromise() already return a promise, you don't need to wrap it in a new one, simply use the one you got!
For your example that would simply mean returning it:
return someFunThatReturnsAPromise()
If you want to do some processing of the data, such as only returning a part of the data (the status property in the below example), you do that in a then callback:
return someFunThatReturnsAPromise().then(data => data.status)
When you return in a then callback, it will in turn return a new promise that gets resolved with the data you returned (unless you returned another promise, in which case it will resolve when that promise resolves).
This is how promises are designed to work, by chaining the asynchronous processes and their results.

If you just want to return data, and reject incase of an error then you don't need a then()
return new Promise(function(resolve, reject)
{
someFunThatReturnsAPromise()
.then(data => resolve(data))
.catch(err => reject(err));
});
would be equivalent to
return someFunThatReturnsAPromise()
unless you want to do some processing on data

Related

Typescript: promise.then() still returning a promise [duplicate]

This question already has answers here:
What's the difference between returning value or Promise.resolve from then()
(6 answers)
Closed 3 years ago.
I was of the understanding that the then() promise method always itself returns a promise. Promises are something I'm still getting used to being a bit of a newb, so I've just been going over some examples and tinkering. The following example shows that the return value of the then method is an object.
const foo = true;
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
if (foo) {
resolve('Do this');
} else {
reject(Error("Do that"));
}
}, 1500)
})
const bar = myPromise.then(value => value);
console.log(typeof bar); // object
Is this the same as returning a promise? Or do I need to explicitly tell then to return a promise like so (pseudocode, I know not correct) :
.then(value => {
// do something
return new Promise;
})
I want to make sure I've got this. Really appreciate the help.
Yes, The then() method returns a Promise. It takes up to two arguments: callback functions for the success and failure cases of the Promise.
And the promise is an object and the typeof promise will be an object. You don't need to explicit return a promise.
You can read more about the promises here
Yeah then() always return a promise. However, the pseudocode is incorrect. The function then takes two arguments:
p.then(onFulfilled[, onRejected]);
p.then(value => {
// fulfillment
}, reason => {
// rejection
});
Exactly like the Promise constructor. Then create a promise from another one. We often omit the onRejected argument because of we handle the reject case with catch.
Here an interesting article: https://medium.com/#kevinyckim33/what-are-promises-in-javascript-f1a5fc5b34bf
And the then doc : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

Cannot understand why outer Promise wont resolve

I am a beginner to the weird ways Javascript works, and I am unable to understand the single threaded design and how Promises work.
Take the following code:
function a() {
return new Promise((resolve, reject) => {
var inn = new Promise((resolve, reject) => {
setTimeout(() => reject('Error'), 0);
}).catch((msg) => console.log(msg));
return inn;
});
}
a().then((msg) => console.log('then'));
My questions are the following:
The inner promise fails thats why I get Error printed, but why doesn't the other Promise resolve and get 'then' printed?
Does returning a Promise from a Promise means that the outer promise resolves ?
When I encounter a catch block does it mean the Promise is cancelled ?
Sorry if this is noob but I am unable to exactly find the answers that I looking for, most other posts are just confusing me.
Using new Promise within another new Promise is an antipattern, and what you experience here is a reason why.
You don't call any of the resolve and reject of the outer new Promise. The return inn has no effect, because the outer new Promise is only resolved or rejected, by either calling resolve, reject or by an error that is thrown, and neither of this is happening there.
That's how it should look like:
function a() {
return new Promise((resolve, reject) => {
setTimeout(() => reject('Error'), 0);
}).catch((msg) => console.log(msg));
}
a().then((msg) => console.log('then'));
You only use new Promise if you need to convert something async that does not provide a Promise as a result, into a Promise. And you want to keep the code footprint within that new Promise as small as possible, so that you can be sure that every code path will lead to either a resolve ar reject condition.
So turning a setTimeout into a Promise by wrapping it into a new Promise is fine. But at that point, you have a Promise, so there is no need to wrap that into another new Promise. That breaks the whole purpose of chaining and the guarantees Promises make. (What is the explicit promise construction antipattern and how do I avoid it?)
And you should not use strings as errors. Neither for throw nor for reject use reject(new Error('Error')) (or a custom error object) instead.
You must resolve inn within function a rather than return it in order for the promise chain to continue unbroken.
Because first promise is not resolved/rejected. Check following. I just changed return inn to resolve(inn)
function a() {
return new Promise((resolve, reject) => {
var inn = new Promise((resolve, reject) => {
setTimeout(() => reject('Error'), 0);
}).catch((msg) => console.log(msg));
resolve(inn);
});
}
a().then((msg) => console.log('then'));

Return fetch wrapped by Promise the same as returning fetch?

Background
I started working at a company that doesn't have many patterns and I see the return of fetch calls in two ways. One returning just the fetch call and another returning a fetch call wrapped by Promise using resolve and reject, and this made me get confused.
Question
Is doing this
const returnFetchWrappedByPromise = () => {
return new Promise((resolve, reject) => {
return fetch("url")
.then(resolve(true))
.catch(reject(false))
})
}
The same as this
const returnFetch = () => {
return fetch("url")
.then(() => true)
.catch(() => false)
}
?
If not, what is the difference?
If yes, which one should I use?
Observation: I used true and false just to make an example, but in reality, is some result and some error.
The new Promise object within the returnFetchWrappedByPromise function is not needed. fetch already returns a Promise object (Screenshot below). You should use the returnFetch function. Hope that helps.
fetch inherently returns a promise, so wrapping it in a new Promise doesn't add any functionality. The use of async also does not add anything in this case and actually presents a case of the Promise constructor anti-pattern.
The second function syntax is the preferred way.

Promises chaining, wrong order

I'd like to understand the promises chaining in Javascript. So I wrote this little fiddle:
https://jsfiddle.net/GarfieldKlon/89syq4fh/
It works like intended. c waits for b, and b waits for a.
But when I change these lines to:
a().then( result => console.log(result))
.then( () => {b().then( result => console.log(result))})
.then( () => {c().then( result => console.log(result))});
So I added the curly braces around b and c and then the output is 1, 3, 2. And I don't understand why.
When I add a return then it works again:
a().then( result => console.log(result))
.then( () => {return b().then( result => console.log(result))})
.then( () => {return c().then( result => console.log(result))});
But why? When there are no curly braces you're only allowed to write one statement, correct? And this statement is implicitly returned?
And when you use curly braces you have to explicitly return something?
But why does it mess up the order when using curly braces without return? And why does it still log something when the return is missing?
When there are no curly braces you're only allowed to write one expression which is implicitly returned?
And when you use curly braces you have to explicitly return something?
Yes.
But why does it mess up the order when using curly braces without return? And why does it still log something when the return is missing?
Because the promise then function relies on return values for chaining.
Remember that then returns a new promise for the result of the callback. When that result is another promise, it waits for the result of that inner promise before fulfilling the returned promise - the one on which you are chaining the second then() call.
If your callback starts b().then(…) but returns undefined, the next step in the chain (the c() call) doesn't wait for b to finish.
When using the arrow syntax, you can interpret it in many things:
() => 'hello'
is equivalent to
() => { return 'hello'; }
However, when doing
() => {'hello'}
as similar to what you wrote:
.then( () => {b().then( result => console.log(result))})
then you can interpret that as
() => {'hello'; return;}
So, in the code, yours promise handling b().then( result => console.log(result)) is called before a void return; is done. You are not returning the resulting promise object at all. It gets called when b is finished, no matter of what you were doing.
This has to do with arrow functions. When you omit the curly braces, the return is implicit. So
const f = () => 42;
is equivalent to
const f = () => { return 42; };
Also, b().then(something).then(somenthingElse) is still only one expression, so it can be implicitly returned.
A Promise is an object that represents the result of an asynchronous operation.
It is important to remember that Promises are not just abstract ways registering callbacks to run when some async code finishes — they represent the results of that async code.
When we write a chain of .then() invocations, we are not registering multiple callbacks on a single Promise object. Instead, each invocation of the then() method returns a new Promise object.
That new Promise object is not fulfilled until the function passed to then() is complete. The value that fulfills promise 1 becomes the input to the callback2() function. The callback performs some computation and returns a value v. When the callback returns the value, the promise is resolved with the value v.
When a Promise is resolved with a value that is not itself a Promise, it is immediately fulfilled with that value.
It is important to understand in this case, so I rephrase: if a callback returns a non-Promise, that return value becomes the value of the promise, and the promise is fulfilled.
If the return value v is itself a Promise, then the promise is resolved but not yet fulfilled.
Your case:
allow me to post the functions a,b and c here:
let a = function() {
return new Promise( (resolve, reject) => {
setTimeout(() => resolve(1), 300);
});
}
let b = function() {
return new Promise( (resolve, reject) => {
setTimeout(() => resolve(2), 200);
});
}
let c = function() {
return new Promise( (resolve, reject) => {
setTimeout(() => resolve(3), 100);
});
}
and the implementation
a().then( result => console.log(result))
.then( () => {b().then( result => console.log(result))})
.then( () => {c().then( result => console.log(result))});
Here is what is happening
By adding the curly braces to the arrow function body, we no longer get the automatic return.
This function now returns undefined instead of returning a Promise, which means that the current Promise is fulfilled and next stage in this Promise chain will be invoked with undefined as its input.
So, function a gets invoked, returns a promise, which is, once fulfilled invokes the callback1.
callback 1 returnes undefined so the promise1 is fulfilled and the next .then() invokes the callback2.
The callback2 invokes the b which itself returnes a Promise, but this Promise is not returned by the callback2. The callback2 returns undefined. The Promise2 is fulfilled with undefined and life goes on - Callback3 gets invoked.
At this point b and c are running simultaneously, and because c is 100ms faster than b you get the 1,3,2 order.
Terminology
We say that the promise has been fulfilled if and when the first callback (argument of then method) is called.
And we say that the Promise has been rejected if and when the second callback (argument of then method) is called.
If a Promise is neither fulfilled nor rejected, then it is pending. And once a promise is fulfilled or rejected, we say that it is settled.
If the async code runs normally (and the Promise is fulfilled), then that result is essentially the return value of the code.
If the Promise is fulfilled, then the value is a return value that gets passed to any callback functions registered as the first argument of then().
Promises can also be resolved. It is easy to confuse this resolved state with the fulfilled state or with settled state, but it is not precisely the same as either.
Resolved means that another Promise has been assigned to the value of the current Promise. The current Promise has become associated with, or “locked onto,” another Promise.
We don’t know yet whether the Promise will be fulfilled or rejected, because it is not yet settled. Its fate now depends entirely on what happens to Promise

Hard time understanding difference between Promise.resolve() and promise chain

I have some hard time understanding what is the difference between using Promise.resolve() and simple using the promise.
The explanation seems a bit hard to get so i have a little example:
For example, i have a method that return a promise like this:
requestPokemon() {
return new Promise((resolve, reject) => {
axios.get("https://pokeapi.co/api/v2/pokemon/1").then(value => {
resolve(value);
})
.catch(error => {
reject(error);
})
});
}
so, now i can call this method and chain the promise, i figure two ways of do it, and can't get it when Promise.resolve is better or not, my issue is understanding that.
so i solved it in two ways:
first:
Promise.resolve(this.requestPokemon()).then(value => {
this.pokemon = value.data.name;
}).catch(error => {
console.log(error);
})
second:
this.requestPokemon().then(value => {
this.pokemon = value.data.name;
}).catch(error => {
console.log(error);
})
please i need a little explanation of the downsides and upsides on doing it one way above the other, i appreciate the help a lot.
Thanks
At first you dont need to construct a promise (thats an antipattern) in your requestPromise, just return the one from axios:
requestPokemon() {
return axios.get("https://pokeapi.co/api/v2/pokemon/1");
}
Now lets have a look at this line:
Promise.resolve(this.requestPokemon()).then(/*...*/)
It will create a new promise, that resolves or rejects when the axios promise resolves or rejects and adds a then handler to it. So it will be chained like this like this:
resolve() -> Promise (axios) -> Promise (Promise.resolve) -> then
reject() -> Promise (axios) -> Promise (Promise.resolve) -> catch
So as you can see Promise.resolve just passes through the data, so actually it is superflous. We actually just need:
resolve() -> Promise (axios) -> then
reject() -> Promise (axios) -> catch
Which can be done with:
this.requestPokemon().then(/*...*/, /*...*/);
please i need a little explanation of the downsides and upsides on doing it one way above the other
Adding Promise.resolve is just a bit more typing and makes it less readable, there is no syntactical difference.

Categories

Resources