Javascript fetch POST call doesn't wait for resolve [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
I am working on a Python dashboard with FastAPI and Javascript. I have created a POST call returning an URL in FastAPI, which I am trying to fetch with Javascript and pass to the player. The output of this POST call is JSON. I am trying to assign the value of a certain key to the laURL variable. The problem is that even though I am using await and async function, Javascript is not really waiting for resolving the response and the second function is executed before the completion of the laURL assignment.
async function fetchLicense(playbackURL) {
try {
let response = await fetch(apiURL, {
method: "POST"
});
if (response.ok) {
let result = await response.json();
let laURL = JSON.parse(result).la_url;
return await laURL;
} else {
console.log("POST Error: ", response);
}
} catch (error){
console.log("POST Error: ", error);
}
}
And then I am using the returned value in another function:
function fetchSource(playbackURL) {
let laURL = fetchLicense(playbackURL);
const source = {
dash: playbackURL,
drm: {
widevine: {
LA_URL: laURL
},
immediateLicenseRequest: true
}
};
return source;
I have checked and tried a couple of different solutions, but nothing seems to be working.
This should be really something straightforward, but unfortunately, the solution isn't so obvious to me.

Javascript async/await is just syntactic sugar for using Promises. fetchLicense hence returns a promise. You can use Promise.then(/* callback */) to specify what should happen when data is resolved.
If you're unfamiliar with this, the following link might help you understand how it works exactly: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

Related

Fetch API returning "undefined" [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
I am currently learning how to work with APIs, and I am having a little trouble with fetching the data from an API. The code below successfully gets a response but does not actually get any data from the server. How do I go about solving this?
const onClick = () => {
fetch(
`https://collectionapi.metmuseum.org/public/collection/v1/objects/45734`
)
.then(res => {
if (res.ok) {
console.log(res)
console.log('SUCESSS')
} else {
console.log("Not Successful")
}
})
.then(data => {
if (data) {
console.log(data)
} else {
console.log("undefined data")
}
})
.catch(error => console.log('ERROR'))
console.log(results);
}
The promise .then methods can be chained in a way each chained then methods will receive the returned value of the previous one. In your case, the first one does not return any values, making the second one receiving nothing, also well known as undefined.
As the url your code is calling return json content, you should return after loging success the result of res.json().
This will read the stream of the response body and parse it as json, using a promise.

Should I use response.send() in 'finally' block when writing Google Cloud Functions?

Im' trying to understand using promises with Google Cloud Functions a bit better. I just learned about the 'finally' method on promises, which is called after all promises in the chain are fully resolved or rejected. In a http function is it good practice to put response.send() inside of the finally method?
The below code uses request-promise-native for the http request. In the first .then() I call parseSchedule, which uses the cheerio web scraping api to loop through some data and on a website, and add it to the scheduledGames array (synchronously, I think).
I return from that and the then log that data to the console in writeDB, but one thing I noticed is that I see response.send() log 'execution finished' before I see the data from scheduleGames in the log. Is that correct?
Should I be using the 'finally' block like this?
Thanks,
const options = {
uri: 'https://www.cbssports.com/nba/schedule/' + urlDate,
Connection: 'keep-alive',
transform: function (body) {
return cheerio.load(body);
}
};
return request(options)
.then(parseSchedule)
.then(writeSchedule)
.catch((err) => console.log("there was an error: " + err))
.finally(res.send("execution finished"));
function parseSchedule($){
const scheduledGames = [];
$('tbody').children('tr').each((i, element) => {
const gameTime = $(element).children('td').eq(2).find('a').text()
const scheduledGame = { gameTime: gameTime};
scheduledGames.push(scheduledGame);
});
return scheduledGames;
}
function writeDB(scheduledGames){
console.log(scheduledGames);
}
}
It typically makes more sense to send a success response at the time in the promise chain when everything is successful, or send an error response in a catch handler. If you do these two things, it doesn't make sense to use finally at all, since success and error are the only two cases you really need to handle. Unless you have some special case, stick to just success and error.

fetch function return Promise <pending> [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);
});

Need clarification on calling Meteor methods asynchronously

So i've been doing some reading and I think I have a general grasp on this subject but could use some insight from someone more experienced. I've been trying to write a simple RSS reader in Meteor and have been facing some issues with calling the Meteor method asynchronously. I currently define the method on the server(synchronously) and call it on the client(asynchronously). What I don't understand is that when I try to make the HTTP.call on the server, I return an undefined value passed to my client if I pass a callback into the request. But when I make the API request synchronously everything seems to work fine. Is this the normal behavior I should expect/the way I should be making the API call?
Meteor.methods({
getSubReddit(subreddit) {
this.unblock();
const url = 'http://www.reddit.com/r/' + subreddit + '/.rss';
const response = HTTP.get(url, {}, (err, res) => {
if(!err) {
//console.log(res.content);
return res;
} else {
return err;
}
});
}
});
Here's the method defined on the server side. Note that logging res.content shows that I'm actually getting the right content back from the call. I've tried reading some other answers on the topic and seen some things about using Future/wrapAsync, but I'm not sure I get it. Any help would be greatly appreciated!
The HTTP.get is doing async work, so callback passed to it will be called out of this meteor method call context.
To get desired result you should do it like this:
Meteor.methods({
getSubReddit(subreddit) {
// IMPORTANT: unblock methods call queue
this.unblock();
const url = 'http://www.reddit.com/r/' + subreddit + '/.rss';
const httpGetSync = Meteor.wrapAsync(HTTP.get);
try {
const response = httpGetSync(url, {});
//console.log(response.content);
return response.content;
} catch (err) {
// pass error to client
throw new Meteor.Error(...);
}
}
});

Firebase.createUser() - Create a return function [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I would like to create a simple function in Javascript that returns me the result of calling Firebase.createUser() dependent on onComplete.
I've done like this:
function createAUser(email, password) {
if (email === "" || password === "") { return false; }
var
onComplete = function (error, userData) {
if (error) {
switch (error.code) {
case "EMAIL_TAKEN":
console.log("The new user account cannot be created because the email is already in use.");
break;
case "INVALID_EMAIL":
console.log("The specified email is not a valid email.");
break;
default:
console.log("Error creating user:", error);
}
return false;
} else {
console.log("Successfully created user account with uid:", userData.uid);
return true;
}
};
MyFirebaseRootRef.createUser({ email: email, password: password}, onComplete);
/* return something here, true/false based on onComplete */
}
Or.. are there any other way to get me what I want. What I'm essentially after is just to find a way to figure out not only through console.log() how the creating of a user went.
Sorry for typos/bad code, thanks for all responses!
Edit:
Thanks for all responses I've now looked into the callback & the asynchronous stuff (something like starting another thread, and then follow through with the function). I must give it some thought over data, like the stack data in the function must be release upon return, how can this data be followed through to the callback.
Anyhow sorry for duplicate, thanks again
You're dealing with asynchronous data.
The call to create the Firebase user goes over the network, which means we have to patiently wait for the user to come back. But, we don't want to block the only thread we have to do other operations. This means the call will go on the JavaScript event loop and when the network request completes (and the call stack is clear), we will finally get our data back.
To handle this elegantly in code you can use a Promise.
var user = { email: 'my#email.com', password: 'secret' };
var promise = new Promise() {
function(resolve, reject) {
var ref = new Firebase('<my-firebase-app>');
ref.createUser(user, function(error, authData) {
if (error) {
reject(error);
} else {
resolve(authData);
}
});
}
};
promise
.then(function(authData) {
})
.catch(function(error) {
});
Promises are native to modern browsers, but if you want to support older browsers you'll have to use a library like jQuery, Bluebird, or RSVP.
onComplete is a callback. This means that your code is sending a request and when it is completed, onComplete is being called. When you call createUser, the request is being sent and is not completed, so at the line after calling createUser you are not able to get the result of onComplete, because the request is not finished yet. As a result, you need to handle the complete event inside the function you associated to it.

Categories

Resources