How does arrow functions behave when the body is a single line? - javascript

I wanted to know when arrow functions have a single line, the curly braces and the return keyword can be omitted, it implicitly returns whatever is there. But what if I don't want to return anything.
For example in the following code snippet, the first .then should return response.json and this is what the code does, the line is implicitly returned. But in the second .then I don't want to return the console.log but according to me it is also being implicitly returned.
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => console.log(json))
My question is have I understood this properly? And does this really matter because it won't change the results of my program? And if it does what's the way around?

But what if I don't want to return anything.
Your best bet there is to use the verbose form (with curly braces) without a return. But note that even then, calling a function always ends up with a result (even if the function doesn't return anything). That result is undefined if the function doesn't return anything.
You could (ab)use the comma operator, but I discourage you from doing so, and you need () to do it:
.then(json => (console.log(json), void 0));
..not least because it's more verbose than
.then(json => { console.log(json) });
(Of course, console.log returns undefined anyway, so... :-) )
My question is have I understood this properly?
Yes, you seem to (other than a minor quibble with the word "line", see the "Side Note" below).
And does this really matter because it won't change the results of my program? And if it does what's the way around?
It certainly doesn't matter with a function like console.log that returns undefined. If nothing is using the promise returned by that final then, then no, it doesn't matter.
FWIW, the real problems with the code in the question are:
It doesn't look for HTTP success before calling json. This is a footgun in the fetch API: It only rejects the promise on network errors, not HTTP errors.
It doesn't handle rejections.
Fixing those:
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => {
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response.json();
.then(json => console.log(json))
.catch(error => {
// Handle/report error
});
Side note:
...when the body is a single line?
Lines aren't relevant here. What's relevant is that the first non-whitespace character after the => is or isn't a {. If it is, the arrow function has a function body and explicit return is required if you want to return something other than undefined. If it isn't, the arrow function has a concise body which is a single expression, the result of which is returned from the function.

have I understood this properly?
You understood properly, everything you said is good
does this really matter because it won't change the results of my program?
it doesn't really matter, it doesn't change the result of your program, it could change it if you had a 3rd then as the value returned by the console.log would become the parameter for your 3rd then callback
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => console.log(json))
.then(value => /*value is the value returned by console.log which is undefined*/)
but you're not forced to use this value it's up to you
what's the way around?
if you don't want to get the value returned by the operation then you can add curly braces
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => {console.log(json)})
.then(value => /*still undefined because a function without return still return undefined by design of the language*/)

Related

How to get the result from a pending Promise? [[PromiseResult]] [duplicate]

This question already has answers here:
Why does .json() return a promise?
(6 answers)
Closed 11 months ago.
So my code here return a Promise and since I'm using then syntax I don't know why that happens :-??
fetch('someurltoAJsonFile.json')
.then(function(response) {
console.log(response.json());});
response.json() in node-fetch library also returns a promise, instead try
fetch('someurltoAJsonFile.json')
.then(response => response.json())
.then(data => {
console.log(data)
});
you can look up more details about it here
EDIT:
It seems that the returned response wasn't in the valid json, so for the sake of completeness here is a code for text
fetch('someurltoAJsonFile.json')
.then(response => response.text())
.then(data => {
console.log(data)
});
The function given as then parameter will be executed asynchronously (sometime in the future when your server returns a response), but then itself return Promise immediately (in synchronous way) by its definition
If you want to code looks less nested (more as synchronous code) you can use await but you must opaque whole code with async function
async function load()
{
let response = await fetch('someurltoAJsonFile.json');
let data = await response.json();
console.log(data);
}
Debating whether or not this qualifies as an answer, but I ran into a similar situation today that led me to this question even though my problem ended up being environment related.
If you are seeing promise pending and your code is correct and you spend way too much time trying to figure out why the console.log isn't showing, double check that you have "Info" turned on in chrome's dev tools. I only had warnings turned on so I wasn't seeing my console.log.
This code works and show a good way to make a fetch and get the promise without the pending problem.
Run this code in your server if you have cors problem download this extension in google chrome "Allow CORS: Access-Control-Allow-Origin"
async function invoices()
{
let response = await fetch('https://blockchain.info/latestblock?utm_medium=referral&utm_campaign=ZEEF&utm_source=https%3A%2F%2Fjson-datasets.zeef.com%2Fjdorfman');
let data = await response.json();
console.log(data);
return data;
}
invoices().then(data => {
console.log(data);
});

Passing parameters to a promise

I am trying to write a promise in such a way that I can pass some parameters. Inside, this promise will call a Fetch. This is the code I wrote so far:
const myFunction = (parA, parB, parC) => {
return new Promise ((resolve, reject) => {
url = ... // calculated based on the parameters passed above;
fetch(url)
.then(response => {
var object = response.json();
resolve(object);// the idea is that 'object' is returned by the outmost promise
console.log('Check');// So far OK, this is correctly printed to the console
})
.catch(err => {
console.log('Error: ' + err);
reject(err);
});
// resolve('1') // Used for test only. With this, everything works, but "object" here is undefined -- I guess it gets executed too early, before the completion of the Fetch
});
and this is where the promise is called
myFunction(a, b, c).then(res => {
console.log('OK');// just testing
console.log(res);// just testing
});
What happens is that the Fetch resolves OK, but my overall promise doesn't. The last two console.log instructions are never executed.
In short, my problem is: how can I resolve my promise returning the result from the Fetch? It's a promise inside a promise, I guess I could chain them with .then, but I also want to be able to pass parameters.
I also guess I could rewrite the code avoiding this promise chaining, but since I'm also doing it as a way of learning, I prefer to try to figure out first how to solve this problem with this structure.
p.s.: at the moment I am stuck with the promises, cannot use async/await because I am with an old version of node.js and cannot update it
As #VLAZ already mentioned, it's not necessary to create your own promise here, since fetch() itself already returns a promise.
Therefore, you could try this:
const myFunction = (parA, parB, parC) => {
const url = ... // calculated based on the parameters passed above;
return fetch(url)
.then(response => response.json())
.then(object => {
console.log('Check', object);
return object;
})
.catch(err => {
console.log('Error: ' + err);
});
};

Trouble with axios returning promise object

I imagine it's something really simple, but I'm having some trouble getting the correct response. My code is returning the promise object, and not the value.
My axios call is something like this:
export const myFunc = async (hash: string) => {
return axios.get(`${url}/${path}?hash=hash`)
.then((response: any) => {
console.log('my response: ', response.data) // {key: value} as expected
return response.data
})
}
I call it from another file
const xy = async (c: string) => {
return myFunc(c)
}
console.log('result of xy(): ' xy('some hash')) // result of xy(): { Promise <pending> } <--- ????
If I .toString() it, because I'm annoyed (and I think I had some reason why at one point but I don't remember what that is), I get
result of xy(): [object Promise]
I've googled, I've stack overflowed, and now I'm asking the question because what I've found so far doesn't quite work.
Thanks for you help
Explicit promise syntax fixed the issue. I'm sure I was missing something really simple. Thanks much to #EmileBergeron. But we also decided that the data didn't need to be encrypted at rest, so by storing this non sensitive data in an unencrypted state, we no longer needed to make a separate rest call to un-encrypt the hash and didn't need to worry about working in an additional promise in the first place.

Usage of response in React

Can someone highlight the difference between these 2 code snippets in React?
window.fetch(url)
.then((response) => {
console.log(response.json().content);
})
and
window.fetch(url)
.then((response) => response.json())
.then((data) =>{
console.log(data.content);
})
response contains a Java object and content is one of the fields in
that object.
2nd snippet prints the correct value of content whereas 1st snippet prints undefined.
Edit: My question is not about "why response gives a Promise rather than a normal object". It is more about what are the implications of response returning a promise.
The below snippet doesn't work because response.json() returns a Promise and not a simple object which is why in the second snippet it returns a correct value as you are using .then to get the value
window.fetch(url)
.then((response) => {
console.log(response.json().content); // response.json() is not an object but a promise and hence you can't access content from it directly
})
The second snippet is equilvalent to
window.fetch(url)
.then((response) => {
response.json().then((content) => console.log(content));
})
but an be simplified to chainable promises by returning the response.json() promise from the first .then as shown in your second snippet
This is because response.json() returns promise.As it returns promise, so another then is used to catch its response. More info about promises can be found here.
While using javascript fetch you need to convert response to json using response.json(). You can skip extra step of converting response to json by using axios e.g.
axios.get(url)
.then(res => {console.log(res)})

angular2 : issue with rest api

I am trying to learn angular2 (coming from php scripts, it is quite difficult^^), using a real rest api in "Tour of Heroes".
From what I read, I thought it could be simple...
I have a working api, built with Express :
curl -XGET http://localhost:3001/heroes
[{"_id":"58185c8a8af4b512c51c0519","no":"1","name":"bahamut","__v":0,"updated_at":"2016-11-01T09:12:42.803Z"},{"_id":"58185ca78af4b512c51c051a","no":"2","name":"gatz","__v":0,"updated_at":"2016-11-01T09:13:11.063Z"},{"_id":"58185ec98af4b512c51c051b","no":"3","nam...
In hero.service.ts, I can get the data :
getHeroes(): Promise<Hero[]> { // {{{
console.log('getheroes in service');
console.log( "%o", this.http.get(this.heroesUrl).toPromise());
return this.http.get(this.heroesUrl)
.toPromise()
.then(response => response.json().data as Hero[])
.catch(this.handleError);
} // }}}
console screenshot
When I do same console.log on original "Tour of Heroes", I have an array in data whereas here I have a string...
I guess I have to convert somewhere the string but whatever I tried, it does not work.
(I read many examples with Observable too but I have not succeeded either)
Help wanted to explain me how to...
TIA
JP
You're so close! The mistake here is in how you handle Promises, along with misunderstanding how they return. In this case you were trying to assign an undefined property (response.json().data) when you meant to coerce response.json() as type Hero[] then return.
What you'll need to do is ensure you have a matching type to assign your response when it's converted to a JSON with that json() call. The Hero type in the guide does not match your response, and you'll have errors because of that.
To check that you're receiving a response, make a call to the service's getHeroes() function and log the returned value. Logging internally to the function can be done, but that would be where understanding how Promises work in depth would help more than anything.
getHeroes(): Promise<Hero[]> {
return this.http.get(this.heroesUrl)
.toPromise()
.then((response) => response.json() as Hero[])
.catch(this.handleError);
}
If you want to know I'm not crazy, here's the code to log internally. This should log your response no matter what type is received.
getHeroes(): Promise<Hero[]> {
return this.http.get(this.heroesUrl)
.toPromise()
.then((response) => {
console.log(response.json());
})
.catch(this.handleError);
}
For further context into why you do these then() calls, a Promise returns asynchronously which means the result is only available after an indeterminate amount of time has passed. Any execution that must wait for the result must either happen in the then() calls or after the function returns an actual value. As JS functions run synchronously if you try to execute the following example you'll see a printout of undefined rather than a string response. This is because the console.log(r) is called immediately after the promise call, completely oblivious to the fact it hasn't actually let r be assigned a value.
getHeroes(): Promise<Hero[]> {
var r;
this.http.get(this.heroesUrl)
.toPromise()
.then((response) => r = response.json())
.catch(this.handleError);
console.log(r);
}

Categories