The code:
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
const raw = JSON.stringify({
email: "[email protected]",
password: "password",
});
const requestOptions = {
method: "POST",
headers: myHeaders,
body: raw,
redirect: "follow",
};
let data;
fetch("/users/login", requestOptions)
.then((response) => response.text())
.then((result) => {
data = JSON.parse(result);
})
.catch((error) => console.log("error", error));
console.log(data);
The result I'm getting is undefined. The result I want is result object from fetch to be stored in data with async/await.
The code:
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
const raw = JSON.stringify({
email: "[email protected]",
password: "password",
});
const requestOptions = {
method: "POST",
headers: myHeaders,
body: raw,
redirect: "follow",
};
let data;
fetch("/users/login", requestOptions)
.then((response) => response.text())
.then((result) => {
data = JSON.parse(result);
})
.catch((error) => console.log("error", error));
console.log(data);
The result I'm getting is undefined. The result I want is result object from fetch to be stored in data with async/await.
Share Improve this question edited Dec 11, 2020 at 18:11 Dani Mesejo 62k6 gold badges53 silver badges84 bronze badges asked Dec 11, 2020 at 18:09 vturkovicvturkovic 1372 silver badges10 bronze badges2 Answers
Reset to default 4Your call to console.log
is being executed before the request has finished and the data has been received.
The order of execution differs from the order your code is written. The likely chain of events is:
- Create undefined variable named
data
- Fire off a request to
/users/login
with the fetch API which will be executed asynchronously - Call to
console.log
with a reference todata
which is stillundefined
- Request has pleted, so the callback passed to
fetch.then
is called, anddata
is defined
You'd need to wait until the request is plete and the response is parsed before doing something with data
.
You can do this in a couple of different ways. Using promises:
let data;
fetch("/users/login", requestOptions)
.then((response) => response.text())
.then((result) => {
data = JSON.parse(result);
// Now that `data` has been defined, we can do something with it
console.log(data);
})
.catch((error) => console.log("error", error));
With async/await
// Note the async keyword
async function foobar() {
let data;
// Note the await keyword
await fetch("/users/login", requestOptions)
.then((response) => response.text())
.then((result) => {
data = JSON.parse(result);
})
.catch((error) => console.log("error", error));
console.log(data);
}
// There are other improvements that could be made to this example also
// to make it more idiomatic. For example:
async function foobar() {
let data;
// Use try/catch instead of `Promise.catch`
try {
const response = await fetch('/users/login', requestOptions);
// Use the `.json` method on the fetch response object
data = await response.json();
} catch (error) {
console.log('error', error);
}
console.log(data);
}
The important thing to note is that any action that occurs in the context of a promise (in your case, assignment to data
will occur asynchronously. The action may or may not have been pleted at any given moment.
Using async/await is usually remend as best practice these days. This requires ES6 support, but that's usually a given in 2020 and has been supported in browsers and Node for years at this point.
Using async/await allows you to write asynchronous code without the dreaded "callback hell" of Promises, and allows you to write more expressive & readable code that closer resembles procedural code.
One thing to bear in mind when using async/await is that the await
keyword can only be used in a function that is marked as asynchronous with the async
keyword, as in the above example.
You can't print a variable that its value initialized in asynchronous block.
It will print the data correctly if you changed it to be like that.
fetch("/users/login", requestOptions)
.then((response) => response.text())
.then((result) => {
const data = JSON.parse(result);
console.log(data);
})
.catch((error) => console.log("error", error));
So to make an action to this data you have to do it inside the then block as it the resolve function for this promise.
otherwise, you can use the async/await
syntax if it's supported.
simply you can make it like that.
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
const raw = JSON.stringify({
email: "[email protected]",
password: "password",
});
const requestOptions = {
method: "POST",
headers: myHeaders,
body: raw,
redirect: "follow",
};
try{
const data = await fetch("/users/login", requestOptions);
console.log(data);
catch(err){
console.log('error', err);
}