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.
Related
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
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.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I am relative new to node.js and I ran into a problem where a function is returning undefined. I use console.log to make sure that it returns the proper value and it does. But in the script that makes the call to the function shows as undefined. I think this may be an issue with async programming? I am trying to learn more on how promises work in node.js. What am I doing wrong?
The reason why I believe that it is a problem with async is because console.log is printing to the console undefined before the console.log in getCurrentFrameName();. var name is being assigned undefined.
frameHandler.switchToFrame('top_page');
var name = frameHandler.getCurrentFrameName();
console.log(name);
The console.log in this method prints to the console after the console.log in the code above. The value printed to the console of name is top_page.
this.getCurrentFrameName = function()
{
driver.executeScript('return self.name').then(function(name) {
console.log(name);
return name;
});
};
You can do this:
this.getCurrentFrameName = function(callback) {
driver.executeScript('return self.name').then(function(name) {
return callback(name);
});
};
and then call it like this:
frameHandler.getCurrentFrameName(function(name) {
console.log(name);
});
this will fix your problem, but yes, is a sync problem.
Yes, this is an issue with asynchronous programming. You cannot return a value from an asynchronous callback.
This is because the callback waits for the asynchronous script to execute, and so, node immediately passes control to the next line after the callback.
In your case, console.log(name); gets called before the callback is executed. Hence, the undefined.
The simplest solution to the current situation is to perform the necessary computations within the callback itself.
However, in more complicated situations (such as, callback within callback) you can easily end up with what is known as callback hell.
There are several ways to deal with callback hell: one of them is something called Promise.
What a Promise does essentially, is that it brings a sense of linearity to the code, thus making it easier to understand and maintain.
In your case, you can do this:
this.getCurrentFrameName = function() {
var myPromise = driver.executeScript('return self.name');
myPromise.then(function(name) {
// Do all computation with `name` here
});
};
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
As a JQUERY/d3-noob, it seems I cannot figure out how to make this work:
supdog = d3.json(dataPath, function(jsondata){
return jsondata;
})
console.log(supdog);
Thanks in advance.
Besides the fact that your problem description is very terse, the problem seems to be your assumptions about what is returning what.
The function d3.json() is an asynchronous function that directly returns (with an undefined value I assume). Only when the data is received from the backend, the callback function you passed to it will be called. Obviously the context is different here and the return value of your callback will not automatically become the return value of d3.json (as this one has returned "long" before already).
What you want to do is probably something like:
var jsondata;
d3.json(dataPath, function(dataFromServer) {
jsondata = dataFromServer;
}
console.log(jsondata);
Update 1:
Obviously, the above example is still not fully correct. The call to console.log() is made directly after the d3.json() returned. Thus, the server might not have sent the reply fully yet. Therefore, you can only access data when the callback is returned. Fixed example:
var jsondata;
function doSomethingWithData() {
console.log(jsondata);
}
d3.json(dataPath, function(dataFromServer) {
jsondata = dataFromServer;
doSomethingWithData();
})
For a (somewhat stupid, but) working example see: http://jsfiddle.net/GhpBt/10/
Update 2:
The above example demonstrates in which order the code is executed but does not really deserve a price for most beautiful code. I myself would not use this "global" variable and simplify the above example to:
function doSomethingWithData(jsondata) {
console.log(jsondata);
}
d3.json(dataPath, doSomethingWithData);
Note how doSomethingWithData is directly passed to d3.json in stead of calling it separately in an anonymous inner function.
Note: This is not a particular problem of d3.js. Basically, all javascript functions that are asynchronous are likely to behave in a similar way. If they return something, it will not be the return value of the passed callback.
Solutions do not work anymore, if you start with the current d3 version. New solution -> Code within d3.json() callback is not executed
Then it must be...
d3.json("filename.json")
.then(function(data){
console.log(data);
});
I'm aware that this is a very old post, but I've faced a similar problem recently, and found the following solution, which might worth sharing:
In my case the JSON file's syntax was broken. By default, no errors pop up in the browser in this case, unless you enhance the function suggested by #BertjanBroeksema with errorhandling. Something like this:
function doSomethingWithData(error, jsondata) {
console.log("error:", error)
console.log(jsondata);
}
This way you'll see if there was something wrong with the processing of the JSON file.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
Like a person asked here (but his solutions as to call a nother function) https://stackoverflow.com/a/10796326/315200 ...I would like to know if its possible to have a function which doesn't call a second function on response of an async request, but simply return when the async request responses.
Something like this maybe:
function callToFacebook() {
var fbResponse;
FB.api('/me', function (response) {
fbResponse = response;
});
return fbResponse; //Will return undefined because CallToFacebook is async
}
Isn't that possible some way, without calling another function??
What I'm trying to achieve is to have one function I can call with some parameters, which will return the response object from a async webservice, like FB.
In short, no. You cannot have an asynchronous function return a meaningful value synchronously, because that value does not exist at that time (as it is built asynchronously in the background).
You can, however, return a Promise object, representing the "potential return value" of the asynchronous operation, and bind a function to that object using done() or similar. That way, your function gets return semantics (instead of having to chain the control flow into a callback), and remains asynchronous.
No, it's not possible.
You can't return value that is returned from async operation.
Think about it, you tell 10 people to have one mile running contest, they start now, will finish in one minute +-, but you want to know the answer now, it's not possible unless you're cheating...