Why is firebase returning a pomise? [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I have checked and read the other posts about making an asynchronous calls which tells me to handle the promise, this post is different because I am expecting my call to have already handled that
I am trying to get the current score of a specified user. However, instead of returning the score I am getting (in the console):
the current score in my firebase database is 3. Here is the function I have:
function getCurrentScore() {
var userId = firebase.auth().currentUser.uid;
return firebase.database().ref('/users/' + userId).child('score').once('value').then(function(snapshot) {
console.log(snapshot.val());
});
}
what I want to do is assign the value to a variable that I can use. For example
var score = getCurrentScore();
How can I get this value and assign it to a variable in firebase?
Edit for clarification:
So, I know that this is making an asynchronous call, however I thought that .then only works once that call has completed. Is this not the case? Does firebase handle this differently?
Here is what I thought from https://howtofirebase.com/promises-for-firebase-bbb9d0d595ed:
Returning a value out of a .then() callback and returning Promise.resolve() has the same result.
I am a noob junior so please do not crucify me. Extra points for detailed explanations that help me learn and increase my understanding..

What i do usually in this type of cases is that i return the promise from the function and handle the promise directly where i need the returned data. e.g i would change it to
function getCurrentScore() {
var userId = firebase.auth().currentUser.uid;
return firebase.database().ref('/users/' + userId).child('score').once('value');
}
And than wherever i need the data i would do:
getCurrentScore().then(function(snapshot){
var score = snapshot.val();
})
Or you can also work something out with async/await to(still a promise). The main point is you leave the responsibility of handling promise to the function which needs the data

Related

Unable to reset array in asynchronous Node.js function despite using Callbacks [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Wait for all promises to resolve
(5 answers)
How to return many Promises and wait for them all before doing other stuff
(6 answers)
Using async/await with a forEach loop
(33 answers)
Closed last year.
So I am trying to create a basic web scrapper API, and I am using a common function PullArticle() with a nested loop to scrape articles with keywords (different sets of articles and different sets of keywords) depending on the GET request I send.
I need to reset the callback variable "article" between GET requests to keep the data separate, but it just adds on previous calls to each GET request which can duplicate data if I call the same request twice.
I have tried to use a callback function and previously a promise function on advice of StackOverFlow, as I was under the impression that the Topic.forEach function was running asynchronously causing the returned "article" to just return empty; however, I haven't been able to get it to work no matter what, and I was hoping somebody can point out what I'm, doing wrong here.
var article = []
function PullArticle (Topic, myCallback) {
article =[] // IF I LEAVE THIS RESET OUT ARRAY RETURNS EMPTY :(
Topic.forEach(TopicLoop => {
newspapers.forEach(newspapers =>{
axios.get(newspapers.address) // pulling html
.then((response)=>{
const html = response.data
const $ = cheerio.load(html) //allows to pickout elements
$(`a:contains(${TopicLoop})`,html).each(function () {
const title = $(this).text()
const url = $(this).attr('href')
article.push ({
title,
url: newspapers.base + url,
source: newspapers.name,
})
})
})
})
})
let sendback = article
myCallback(sendback)
}
In the same file I make a get request with
app.get('/TopicMatrix1',(req,res) =>{
PullArticle( Topic1, myDisplayer)
function myDisplayer (PrintArticle){
res.json(PrintArticle)
}
})
app.get('/SomeOtherTopic',(req,res) =>{
PullArticle()
etc
}
Also does anyone know why I can't make the function myDisplayer(), which prints out res.json a common function sitting outside the GET request, so separate GET requests can call it?

How do I pass result of asynchronous function to a redirect? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
I have a function which is returning information from an API call,part of which is an access token. I then need to plug that access token into the parameters of a redirect URL. Only problem is that thw redirect is invoked before the data is returned. Any ideas on how I can wait till the data is returned before invoking the redirect?
Here's the code:
oauthClient.createToken(req.url)
.then((authResponse) => {
oauth2_token_json = JSON.stringify(authResponse.getJson(), null,2);
let newToken = JSON.parse(oauth2_token_json)
accessToken = newToken.access_token
})
.catch((e) => {
console.error(e);
});
res.redirect(`http://localhost:3000/?token=${accessToken}`)
});
Add one more .then() and make sure the previous .then() returns the authToken (or any variable). Now run that logic of res.redirect(..).. in the next nested .then().
This way you are making sure, the code waits for the asynchronous part to finish off first. then-ables are the best way to make sure your code only runs once the promise is resolved. JavaScript executioner jumps to next line of code once it sees a asynchronous code block, i.e., could be a promise, .then()s, async-awaits.
This was the reason why, res.redirect() was running a little earlier.

Wait for promises inside loop before return [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I got some problems, to getting my code to do as i want.
I want to loop through all my newly created object from the movieList array, once the outer "getJSON" is done. But i can see that the array is empty when i loop through it.
Is there anyway to get this solution to work?
var url = "https://api.themoviedb.org/3/movie/popular?api_key=2c2a6a5ed606126f48db4cdbca91c0f0&language=en-US&page=1";
var genreUrl = "https://api.themoviedb.org/3/genre/movie/list?api_key=2c2a6a5ed606126f48db4cdbca91c0f0&language=en-US";
$.getJSON(url).then(function(movies){
var movieList = [];
movies.results.forEach(function(movie){
/* Get the genere names for single movie */
$.getJSON(genreUrl).then(function(genresHolder){
var genreNames = [];
//Pushes some info to the array
return genreNames;
}).then(function(genres){
movieList.push(new Movie(movie.id,movie.original_title,genres,movie.poster_path,movie.vote_count,movie.vote_average,movie.release_date));
})
counter++;
})
return movieList;
}).then(function (movieList){
movieList.forEach(function(movie){
//Appending each movie to html page
})
}).catch(function(err){
console.log(err)
})
Well, without more specifications in what getJSON is doing, it is difficult to say. But uour code should work. BUT most probably you are resolving getJSON without giving back the result from the url.
In a promise you can simply resolve() or resolve(value), whatever is passed in the call will go to the then(...) function.
I cannot see other obvious error, in this async calls then will be called ONLY after the promise is resolves.

How to return data from promise [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
The community reviewed whether to reopen this question 11 months ago and left it closed:
Original close reason(s) were not resolved
I need to get the response.data out of the promise so it can be returned by the enclosing function. I know, I probably can't do it the way I've coded it because of normal JavaScript scope. Is there any way, it can be done?
The console.log at #1 produces the correct data. console.log #2 always produces 'a';
function addSiteParentId(nodeId) {
var theParentId = 'a';
var parentId = relationsManagerResource.GetParentId(nodeId)
.then(function(response){
theParentId = response.data;
console.log(theParentId); // #1
});
console.log(theParentId); // #2
return theParentId;
}
Any pointers would be appreciated.
One of the fundamental principles behind a promise is that it's handled asynchronously. This means that you cannot create a promise and then immediately use its result synchronously in your code (e.g. it's not possible to return the result of a promise from within the function that initiated the promise).
What you likely want to do instead is to return the entire promise itself. Then whatever function needs its result can call .then() on the promise, and the result will be there when the promise has been resolved.
Here is a resource from HTML5Rocks that goes over the lifecycle of a promise, and how its output is resolved asynchronously:
https://web.dev/promises/
I also don't like using a function to handle a property which has been resolved again and again in every controller and service. Seem I'm not alone :D
Don't tried to get result with a promise as a variable, of course no way. But I found and use a solution below to access to the result as a property.
Firstly, write result to a property of your service:
app.factory('your_factory',function(){
var theParentIdResult = null;
var factoryReturn = {
theParentId: theParentIdResult,
addSiteParentId : addSiteParentId
};
return factoryReturn;
function addSiteParentId(nodeId) {
var theParentId = 'a';
var parentId = relationsManagerResource.GetParentId(nodeId)
.then(function(response){
factoryReturn.theParentIdResult = response.data;
console.log(theParentId); // #1
});
}
})
Now, we just need to ensure that method addSiteParentId always be resolved before we accessed to property theParentId. We can achieve this by using some ways.
Use resolve in router method:
resolve: {
parentId: function (your_factory) {
your_factory.addSiteParentId();
}
}
then in controller and other services used in your router, just call your_factory.theParentId to get your property.
Referce here for more information:
http://odetocode.com/blogs/scott/archive/2014/05/20/using-resolve-in-angularjs-routes.aspx
Use run method of app to resolve your service.
app.run(function (your_factory) { your_factory.addSiteParentId(); })
Inject it in the first controller or services of the controller. In the controller we can call all required init services. Then all remain controllers as children of main controller can be accessed to this property normally as you want.
Chose your ways depend on your context depend on scope of your variable and reading frequency of your variable.
You have to return a promise instead of a variable.
So in your function just return:
return relationsManagerResource.GetParentId(nodeId)
And later resolve the returned promise.
Or you can make another deferred and resolve theParentId with it.

What is the use of the .then function in javascript? [duplicate]

This question already has answers here:
jQuery deferreds and promises - .then() vs .done()
(11 answers)
Closed 7 years ago.
There is not much answer for this simple question that I have. My main question is that I have seen the .then method used a lot in JavaScript and I know the main thing where randomobject.then(//This returns success, //this returns failure). But there are things that I don't get such as the code here:
var success = function (response) {
return response.data;
};
var error = function (errResponse) {
$log.error(errResponse.data.Message);
};
function getsomeData() {
var url = baseUrl + 'api/somedata';
return $http.get(url).then(success, error);
}
First off in that code I'm wondering how the var success knows what data it is getting and the same with error. It says response.data but what is response? It's probably the result of the http.get but that doesn't make much sense code wise. Also it seems that when I have a function for example.
getsomeData returns what it returns. Why doesn't it work if I do the ff:
var dataHolder = randomAngularService.getsomeData()
it returns an object that holds a data under $$state but somehow the .then makes it work if you do the ff:
randomAngularService.getsomeData().then(function (response) {
if(response != null) {
console.log('got the data');
$scope.meeData = response;
}
});
I thought the .then only takes two parameters? This is what's confusing me.
Also is the .then property a JavaScript method or a jQuery one?
It's used to replace (or provide an alternate way) the old callback mechanism with a cleaner way to handle asynchronous requests, instead of passing your callbacks as parameters, you can chain your function with .then, given function will be executed once the promise gets resolved.
Anyhow, this is just a basic explanation, you should really get into the books of promises for more info.
I'm lazy to explain the whole promise thing, but just to answer question about .then
The 2 arguments inside .then actually means "call this function when the promise is resolved(success)/rejected(failed)"
About the arguments inside the functions, they should be specified in the API, because the caller (for instance $http.get) get to decide what to pass when calling that function.

Categories

Resources