rpc.getUserInfo(function(result){
userdata = result;
}); //How can i get the value of "userdata"?
I try:
var userdata = "";
rpc.getUserInfo(function(result){
userdata = result;
});
alert(userdata); // it's "undefined"
Time for some assumptions:
RPC usually stands for Remote Procedure Call
This suggests you are performing Ajax
A standard pattern for Ajax functions is to accept a callback function which runs when the call is complete.
Ajax is Asynchronous, so you can't make an Ajax call, wait for the response, then run the next line of the function that made the call.
Rewrite the script so that whatever you want to do when the Ajax data comes back is done in the callback and not in the function that makes the call (which is where it is now).
Wrong:
var userdata = "";
rpc.getUserInfo(function(result){
userdata = result;
});
alert(userdata);
Right:
rpc.getUserInfo(function(result){
alert(result);
});
You haven't said, but I'm guessing that getUserInfo involves an asynchronous ajax call. That being the case, you can't use the value inline, you can only use it in the callback. E.g.:
rpc.getUserInfo(function(result){
var userdata;
userdata = result;
alert(userdata);
});
You just put all of the logic that you would have put after the getUserInfo call inside the callback instead. That sounds difficult or awkward, but with JavaScript it's trivially easy:
function doSomething() {
var foo;
// Do some setup
foo = 42;
// Here's our first asynchronous call; like all good asynchronous calls,
// it accepts a function to call when it's done
triggerAjaxCall("mumble", function(bar) {
// Now the first call is complete, we can keep processing
// Note that we have access to the vars in our enclosing scope
foo += bar;
// Need to do another asynchronous call
triggerSomeOtherAjaxCall(foo, function(nifty) {
// Now the second call is complete and we can keep working with
// all of our stuff
alert("foo: " + foo + "\n" +
"bar: " + bar + "\n" +
"nifty: " + nifty);
});
});
}
Note that doSomething returns before the first callback is called.
Obviously the anonymous functions above are only appropriate if they're an intrinsic part of doSomething; otherwise, move their functionality into separate named functions.
Related
Just wanting to populate myObj with data from within the get request. According to my console.log(myObj) everythings seems to be their but can't access. I'm sure their is a simple answer to this. Thanks.
function getInfo() {
var myObj = {};
$.get("http://ipinfo.io", function(response) {
myObj.city = response.city;
myObj.region = response.region;
}, "jsonp");
console.log(myObj.city); //undefined
return myObj;
}
var myStuff = getInfo(); //Object {} just as I expected obviously.
console.log(myStuff) // Object shows all my key value pairs but -->
console.log(myStuff.city); // undefined why?
It is more suitable to use promises. You can try something like this:
function getInfo() {
var dfd = $.Deferred();
$.get("http://ipinfo.io", function(response) {
myObj.city = response.city;
myObj.region = response.region;
dfd.resolve(myObj);
}, "jsonp");
// Return the Promise so caller can't change the Deferred
return dfd.promise();
}
getInfo().done(function(myStuff) {
console.log(myStuff);
console.log(myStuff.city);
});
With promises the code is one idea elegant.
$.get is an asynchronous operation which means that it returns immediately (without running the code in your callback function first). The callback will only be executed at some point in the future when the GET request is finished. In the meantime the code following the $.get call will be executed.
What you're seeing is a result of a specific execution order in which the GET request happened not to finish before the following code was executed. In other words you have a race condition.
In theory , if the GET request finished almost instantly, it would be possible for the callback to execute before your log statements and therefore not print undefined. This is highly unlikely, however, as the time it takes to execute log instructions are much(!) less than what it takes to execute the GET request.
To fix the issue you need to ensure that you're log statements are always run only after the GET request is finished. The idiomatic way to do this in JS is with callbacks - e.g. pass a function which contains the code to execute and call it from inside the response handler:
function getInfo(callback) {
var myObj = {};
$.get("http://ipinfo.io", function(response) {
myObj.city = response.city;
myObj.region = response.region;
callback(myObj);
}, "jsonp");
console.log(myObj.city); //undefined
}
getInfo(function(myStuff) {
console.log(myStuff)
console.log(myStuff.city);
});
It return undefine because the request didn't response yet then the function returned the value. Your request was asynchronous meaning your function wont wait for your get request. it would return what ever myObj is.
You can try something like
function getInfo(callback){
$.get(..., function(res){
var myObj = …;
callback(myObj);
}
}
when ever your request is finished, it would call the callback function and pass in the myObj. so you need to pass in a anonymous function that expect 1 argument to pass in the myObj from the response
getInfo(function(data){
//data should be myObj
});
I have the functions below:
(Normally I get the variable msg by doing some query on a XML Object)
function getMsg(callback) {
var msg = "test";
callback(msg);
}
function msgDone() {
var message = null;
getMsg(function(msg) {
message = msg;
});
return message; //Why is message undefined here?
}
My problem is that I get an undefined on message. I have tested the function getMsg(), and it returns the right value.
How will I make the msgDone to return the message that I get from callback? So that it doesn't return undefined?
Thanks
Why is message undefined here?
It won't be, in the code in the question, but my guess is that the real getMsg is an asynchronous operation. That is, when you call it, it starts the process of getting the message but that process completes later, not right away. (For instance, a typical ajax call is like this.)
In that case, the reason message is undefined in the location you marked is that the callback hasn't been called yet, so nothing has ever assigned to message. You can't return the result of an asynchronous call from a function; instead, you have to provide a callback mechanism of your own (simple callbacks, or promises, or similar). E.g.:
function getMsg(callback) {
// Do something asynchronous...
// It's done, call the callback
callback(/*...the data retrieved asynchronously...*/);
}
function msgDone(callback) {
getMsg(function(msg) {
// Presumably you do more processing here...
// ...and then call the callback
callback(msg);
});
}
Then, instead of:
var msg = msgDone();
doSomethingWith(msg);
doSomethingElseWith(msg);
you do:
msgDone(function(msg) {
doSomethingWith(msg);
doSomethingElseWith(msg);
});
I'm having an issue that is burning my head. Basically this is the scenario:
I have a callController() function, which just simple use the jQuery.load() method to load a controller, after loaded, I can play with the returning parameters.
Now... in one of my controllers there is a validation rule I need to check in order to to allow the user to execute certain functionality, however, I create a function like this:
function myValRule() {
var val = callController('blablabla'),
response = "";
val.done(function(data) {
//my business logic
response = something;
}
return response;
}
As you imagine, response, even if It has a value, it returns undefined, so I set a timeout and console.log() it and now it has a value, but I cannot make to return this value even if I put the return into the setTimeout(). So basically when the method call this function to validate it finds it empty.
Can you point me on some direction to solve this issue?
Remember this is asynchronous! The return response; is long gone by the time .done() is actually called.
if you need the value returned in this fashion, look at either supplying a callback function in your myValRule function (that would be called from within .done()) or maybe look at using the $.Deferred api so you can mimic what callController(...) is doing.
Here's an example of both scenarios (with example call to myValRule):
Callback argument
function myValRule(callback){
var val = callController('blablabla'),
val.done(function(data){
var response = /* something */;
callback(response);
});
}
myValRule(function(response){
// here you have response
});
Using $.Deferred
(I assume it's jQuery since there's a .done call)
function myValRule(){
var df = $.Deferred(),
val = callController('blablabla');
val.done(function(data){
var response = /*something */;
df.resolve(response);
}).fail(df.reject);
return df.promise();
}
myValRule().done(function(response){
// here you have response
});
I've seen similar questions asked regarding this problem. I'm pretty new to javascript and I couldn't figure it out.
I have a function which calls another function.
sayHello() has an async call.
var hello_message = null;
function invokeSayHello(msg) {
sayHello(msg);
//next action
return hello_message;
}
function sayHello(msg) {
// simulate async call
setTimeout(function(){hello_message = msg + " World";},1000);
}
In this case hello_message is returned as null. How would I wait for that async call to complete before the next action line executes in invokeSayHello() function so the returned hello_message would not be null.
I think I'm supposed to use a callback but not sure how to do it.. Also, I call invokeSayHello() from a java file using executeScript()/Selenium
Appreciate all the help.
You should use the result inside the callback. You cannot/should not wait for the asynchronous function to complete. The asynchronous pattern assumes that you use the callback.
Like this:
function invokeSayHello(msg) {
sayHello(msg);
}
function sayHello(msg) {
// simulate async call
setTimeout(function(){
var hello_message = msg + " World";
// Here you can process the result, like alerting it for example or
// passing it to another function
alert(hello_message);
}, 1000);
}
So basically in asynchronous programming you forget about the keyword return and start passing callbacks to your javascript functions so that the caller can subscribe to those callbacks and whatever he wanted to do with the results inside the callback..
This problem is actually caused by my not fully understanding jquery.
I have some code that i tried to put in a function to use multiple times.
function actors(query){
$.get("websit.com?title=" + query + "&type=json", function(html){
var result = html;
var obj = eval ("(" + result + ")");
var actor = obj[0].actors;
return actor; //as far as im aware this does nothing
});
return 0; // gets here and returns zero, returning actor here returns undefined
}
The actor variable holds the information i need, however I'm struggling to get the variable out of the function.
Because of the inner function it will run through and get to the return 0;
If i try assign a variable to the inner function it will return an object and not the return variable.
Any solutions or pointers in the right direction would be greatly appreciated.
This question is asked 1000 times monthly. You can not make an asynchronous call act like a synchronous call. That is what the callbacks are for.
You are also using jQuery, there is no need to use eval! Set the right content type and it will parse the data for you.
Basic idea with a callback
function actors(query, callback){
$.getJSON("websit.com?title=" + query + "&type=json", function(data) {
var actor = data[0].actors;
callback(actor);
});
}
function processResults(info){
console.log(info);
}
actors("Something", processResults);
While it's true you can't do just that, I've found that something like this is an acceptable work-around in most cases that I've run in to:
function getMeSomeJSON(query) {
return $.get("websit.com?title=" + query + "&type=json");
}
Which will return the request's response to whatever calls it.
Alternately, you can:
Pass the response to a callback.
Use $.ajax with async: false, however, this is considered bad practice.
Read the documentation. It has some examples, including data type handling. And a simple check should help to determine what to return.
As you have noticed yourself, your ajax response handler executes after the actors function has returned, thus making it rather difficult to return a value. The standard solution would be to return a promise from the actors function. You can read up on promises, or deferred objects, in jquery docs.
This would be my suggestion:
function actors(query){
var actorsPromise = $.Deferred();
$.get("websit.com?title=" + query + "&type=json", function(html){
var result = html;
var obj = eval ("(" + result + ")");
var actor = obj[0].actors;
actorsPromise.resolve(actor);
});
return actorsPromise;
}
actors(/* your query */).done(function(actor) {
//do whatever you need with your actor
});