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);
});
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
I am having a downstream API call which is basically returning a Promise object instead of resolving it and executing it on point.
This is how I am calling the downstream:
const response = testClient.getSession(sessionId);
When I console.log(response) it is prinitng as Promise { <pending> } instead of desired result which it shoudl print from the downstream.
Having known very little about Async/Await, Promises etc I would like to know whihc category does it fall in? And how do I execute that promise first and do the rest of the steps.
However, I have found a temporary work around like this:
response.then(function(result) {
console.log(result.body);
});
But ideally I would want to store the result into response object then and there itself. Please help me understand this. Thanks in advance
What you called a temporary workaround using then is actually the correct way of waiting on the Promise to be fulfilled. You cannot 'force' it to be fulfilled, because the code will execute as fast as it can and allow you to carry on working until then (that's the point of promises) - but you can wait on it to be fulfilled:
You ought also to check to see if the promise gets 'rejected' using catch - ie produces an error:
response.then( function(result) {
console.log(result.body);
}).catch( function(error) {
console.log(error);
});
To use await:
async function thingy(){
const response = await testClient.getSession(sessionId);
}
To use await and check for errors:
async function thingy(){
try {
const response = await testClient.getSession(sessionId);
} catch (error) {
console.error(error);
}
}
Note that when using async, you do generally need to be in a function declared as async.
The idea of the Promise is to allow your program to carry on doing things whilst you wait for the promise to be fulfilled/rejected - for example, you might make several requests at once, and wait for them all:
Promise.all([
getStuff('one'),
getStuff('two'),
getStuff('n')
]);
I'm trying to create saving feature for my little game (Javascript, Axios, Express, NodeJS MongoDB). Problem is that I don't really understand axios promises and async/await features or more accurately I don't know how to implement them into my code. I want to get data from my mongodb and use it in variable/method so I can change stats of player etc. later as needed. I have been reading all possible guides and similiar posts, but I have no idea why they don't work for me. Any help would be appreciated!
After messing around and trying everything I found on web, here's currently part of my code:
case "Load":
function getMySave () {
return axios.get("http://localhost:3000/save", {
params: {
name: username
}
})
.then(response => {
console.log(response.data)
return response.data
})
.catch(error => {
console.log(error);
return Promise.reject(error);
});
}
const waitIgetMySave = async () => {
const playerSave = await getMySave();
return playerSave;
};
playerSave = (waitIgetMySave());
console.log(playerSave)
player = new Player(username, playerSave.class, playerSave.health, playerSave.mana, playerSave.strength, playerSave.agility, playerSave.speed, playerSave.maxhp);
break;
}
But this code just returns following:
Promise { : "pending" }
Object { _id: "5e9945f238a82e084c7cb316", name: "Jesse", class: "Rogue", ..... }
So object itself is working fine, but I can't apply it to anything outside of the axios.get function. It always gives me pending, promise[Object], undefined or such that I can't use in my player object or variables. I'm quite sure that I'm doing something wrong with async/await features where, but after spending few days trying to solve this problem, I'm really running out of options.
And yes, I looked at [How do I return the response from an asynchronous call?
[1]: How do I return the response from an asynchronous call? but that seems to be for Ajax and I just fail to understand and implement those in my own code.
The key principles of async code
You cannot make asynchronous code synchronous.
Promises are tools to manage asynchronous code in a consistent way
The async and await keywords are tools to manage Promises in a way that looks synchronous (but really just does clever stuff with functions going to sleep while they wait and allowing the rest of the program to keep running)
The specific issue with your code
waitIgetMySave is defined as async so it returns a Promise
When you call it (playerSave = (waitIgetMySave());) you do not await it, so you get the promise and not the resolved value from the promise.
(And waitIgetMySave will have gone to sleep while it waits for getMySave to resolve. This allows the rest of the program to keep going, assign the promise to playerSave and log that promise in the meantime).
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)})
This question already has answers here:
Will async/await block a thread node.js
(6 answers)
In JavaScript, does using await inside a loop block the loop?
(8 answers)
Closed 4 years ago.
I was reading Don't Block the Event Loop from the Node.js guide. There was a line saying:
You should make sure you never block the Event Loop. In other words,
each of your JavaScript callbacks should complete quickly. This of
course also applies to your await's, your Promise.then's, and so on.
I started to wonder, what if, some API call to the database which I'm awaiting is taking some time to resolve, does that mean that I have blocked the event loop with that await call?
After that, I started testing some self written codes but after testing I'm still not clear how blocking through await works. Here are some testing codes:
Assuming, that I'm using express for testing. I understand why making 2 API calls to the /test route blocks the event loop in this case.
function someHeavyWork() {
// like calling pbkdf2 function
}
app.get('/test', (req, res) => {
someHeavyWork();
res.json(data);
});
But that doesn't happen in this case.
function fakeDBCall() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data);
}, 5000)
})
}
app.get('/test', async (req, res) => {
const data = await fakeDbCall();
res.json(data);
})
This may be because of my lack of understanding of how blocking works in the case of async/await.
Contrary to what it seems, await does not block. It's just syntactic sugar over promises. Nothing is blocked; it may look blocking to allow code to be synchronous, but that's just sugar over promises. For example, this may look synchronous:
const response = await fetch(…);
const json = await response.json();
const foo = JSON.parse(json); // Using json here, even though my request was async!
But it's not. Once you desugar it, all you get are promises, which are nonblocking:
fetch(…)
.then(response => response.json())
.then(json => {
const foo = JSON.parse(json);
});
It would be absolutely catastrophic if await were blocking. JavaScript runtimes are generally single threaded. That means user interaction and other processes would cease whenever you made a request or some other async operation such as using the filesystem. On a related note, this is, along with dynamic imports, are the main argument against top level await
The async function returns a promise and you are passing in the request and response, I would change the
res.json(data)
to
return res.json(data)
When an async function returns a value the promise is resolved, if the function contains an error the promise is rejected to just for cleanliness returning the res.json(data) will resolve the function.
This question already has answers here:
Why does .json() return a promise?
(6 answers)
Why is the response object from JavaScript fetch API a promise?
(2 answers)
Closed 5 years ago.
I started with JS and actually like the asynchronous aspects (coming from Python) but I am not sure why some functions return a Promise. Specifically, the following code using fetch makes me wonder about what is returned by json():
fetch('https://freegeoip.net/json/8.8.8.8')
.then((response) => {
return response.json()
})
.then((json) => {
Object.keys(json).forEach((key) => {
console.log("got " + key)
})
})
Streaming aside, the HTTP response we get after a GET is a block of text, which is later interpreted by the client to extract the headers, body and other interesting elements - as part of the analysis of the HTTP content.
The point is that this block of text comes in one piece, so the first then() already has the whole response - why is the parsing of the JSON body an asynchronous operation, different from the forEach in the second then()?
In other words, why couldn't I have the followng code working?
fetch('https://freegeoip.net/json/8.8.8.8')
.then((response) => {
Object.keys(response.json()).forEach((key) => {
console.log("got " + key)
})
})
Note: please try to disable your adblocker if the first code does not run correctly (with a ERR_BLOCKED_BY_CLIENT). The second one is intentionnaly incorrect.
Your second snippet doesn't work because response.json() aka body.json() doesn't resolve instantly.
This is because body.JSON() streams and returns a Response using a Promise asynchronously; which must then be captured by a then() callback in order to read / manipulate.
Such is the nature of Promises.
However, such a syntactic flow can still be achieved by leveraging async await.
fetch('https://freegeoip.net/json/8.8.8.8')
.then(async (response) => {
Object.keys(await response.json()).forEach((key) => {
console.log("got " + key)
})
})
You're right - both snippets do the same. In first snippet, following part:
.then((response) => {
return response.json()
})
Is just handling the response in first step and passing result through. This simple case doesn't need to split it into two steps so you can easily use second example.
It can be useful in some cases.