The below code gets a state from latitude/longitude coordinates. How can I extract the value "result.body.region" from the scope of the anonymous function and use it in a higher scope?
latitude=tweets[0].latitude
longitude=tweets[0].longitude
var Request = unirest.get("https://montanaflynn-geocoder.p.mashape.com/reverse?latitude="+myobj.latitude+"&longitude="+myobj.longitude)
.header("X-Mashape-Key", "xxxxxxxxxxxxxxxxxxx")
.header("Accept", "application/json")
.end(function (result) {
state = result.body.region
});
What I want to do is write a callback function that will wait for the asynch request to finish and use that information in a different scope. I am self taught on javascript so I am struggling to understand callbacks. How can I do this?
The code you have already will do that.
You are probably trying to read the value of state before the callback has fired.
This is why we normally put the code to process the data in the callback: to make sure it runs after the asynchronous event has occurred.
Related
I'm sure there's an easy way to do this, but I'm having difficulty wrapping my mind around asynchronous calls and their flows. I'm trying to do a simple assignment statement in javascript, followed by setting a timer to perform operations on that object once it's been assigned. I have something along the lines of:
var info = getInfo();
$timeout(updateInfo(info), 5000);
However, I don't want the timeout to be executed until info is set initially. I've tried looking into using .then or some form of callback, but I haven't successfully determined how to do that. I'm unsure if having the parameter of info in the updateInfo call makes it so that I can't use callbacks in getInfo or what the correct flow is. I've read other articles and stack overflow responses, but couldn't find one dealing with asynchronous assignment and then using that as a paremter in a subsequent call.
getInfo and updateInfo are methods that return Highcharts graph config objects. Without copying over all the specific details:
getInfo: function() {
return {
options: {
chart: {
type: 'line'
}
}
...
}
}
updateInfo: function(info) {
// Here computations are performed on plot series data.
info.series.push(...)
}
Both getInfo and updateInfo looks pretty sync to me.
So there shouldn't be any synchronization problem.
The only thing I noticed is the wrong use of $timeout in your example.
$timeout(updateInfo(info), 5000); this way updateInfo will be called before the timeout starts and the returned value will be passed as a parameter.
In order to call updateInfo after 5 seconds you have to use anonymous function or bind function.
$timeout(function() { updateInfo(info); }, 5000);
$timeout(updateInfo.bind(null, info), 5000);
For more info about bind.
You should remember that although JavaScript does some asynchronous actions, yet the assignment to a variable is synchronous, which means that it occurs at the moment you requested for it, and won't go on to the next line until it's done.
If getInfo itself has the variable info in scope and updates it during the asynchronous call, then you shouldn't assign a value to it in the invocation of the function.
If I confused you, let me guess what you do there (and please provide the getInfo function for clarifying your question).
I'm pretty sure what getInfo does is an ajax call. So if you already use jQuery, you can simply use their ajax function:
function getInfo(){
$.ajax({
url: "/api/items"
}).done(updateInfo);
}
function updateInfo(data){
console.log ('Do something with', data);
}
getInfo();
See full documentation:
http://api.jquery.com/jquery.ajax/
$.getJSON("../../index.php/churchlocator/base", function(data) {
base_url = data.base;
});
alert(base_url);
How can I get base_url in the above code to be accessible outside of the getJSON var?
The right answer here is to put all code that references the result of the ajax call in the success handler for the ajax call. Do not use global variables for this:
$.getJSON("../../index.php/churchlocator/base", function(data) {
var base_url = data.base;
alert(base_url);
// or you may call some other function here and pass it the data
myFunction(base_url);
});
Ajax calls are "asynchronous" (that's what the A in Ajax stands for). What that means is that they complete sometime in the future and your other javascript continues running. When they complete, they will call their success handler. As such, the ONLY way you can know when the data has been returned from the Ajax call is by either placing code inside the success handler to operate on the returned data or by calling a function from that success handler and passing it the data.
This is asynchronous programming and you MUST use this model if you program with asynchronous functionality of any kind. You cannot use traditional sequential programming with asynchronous function calls.
I am having a problem, or perhaps a lack of understanding, with the jQuery execution order of $.get() function. I want to retrieve some information from a database server to use in the $.ready() function. As you all know, when the get returns, it passes the data to a return handler that does something with the data. In my case I want to assign some values to variables declared inside the ready handler function. But the problem is, the return handler of $.get() does not execute until after ready has exited. I was wondering if (a) am I doing this right/is there a better way or if (b) there was a way around this (that is, force the get return handler to execute immediately or some other fix I'm not aware of). I have a feeling this is some closure thing that I'm not getting about JavaScript.
As per request, I'll post an example of what I mean:
$(function() {
var userID;
$.get(uri, function(returnData) {
var parsedData = JSON.parse(returnData);
userID = parsedData.userID;
});
});
So as you can see, I'm declaring a variable in ready. Then using a get call to the database to retrieve the data needed. Then I parse the JSON that is returned and assign the userID to the variable declared before. I've tested it with a couple alerts. An alert after the get shows userID as undefined but then an alert in get's return handler shows it to be assigned.
$.get() is asynchronous. You have to use a callback to fill your variable and do the computation after the request is complete. Something like:
$(document).ready(function(){
$.get( "yourUrl", function( data, textStatus, jqXHR ) {
var myData = data; // data contains the response content
// perform your processing here...
registerHandlers( myData ); // you can only pass "data" off course...
});
});
// your function to register the handlers as you said you need to.
function registerHandlers( data ) {
// registering handlers...
}
$.get is an ajax request. A in AJAX stand for asynchronous, so script won't wait for this request to finish, but instead will proceed further with your code.
You can either use complete callback or you can use $.ajax and set async to false to perform synchronous request.
The $.get() function executes an async httprequest, so the callback function will be executed whenever this request returns something. You should handle this callback outside of $.ready()
Maybe if you explain exactly what do you want to do, it would be easier to help!
Are you looking for something like:
$(document).ready(function(){
var variable1, variable 2;
$.get('mydata.url', function(data){
variable1 = data.mydata1;
variable2 = data.mydata2;
});
});
If you declare the variables first, then you can set their values within the get call. You can add a function call at the end of the get handler to call a separate function using these values? Without some kind of example, its hard to go into any more detail.
Without seeing the full code, my guess is that you should declare your variable outside $.ready; initialize it in ready for the initial page load; then update it from the get callback handler.
for example
var x = ""; // declaration
$(document).ready(function() { x = "initial value"; });
$.get(...).success(function() { x = "updated from ajax"; });
I'm trying to send a request and then in callback function, change the parameters and then send the request again. Something like this:
function sendRequest() {
params = {param1:'value', param2:'value'};
while(params) {
$.getJSON("url", params, function(data) {
if(data contains something important)
params.foo = bar;
else
params = null;
});
}
}
But params never changes and the while loop continues for ever. It seems to be a reference problem; but I can't figure out how to solve this. Thanks in advance.
The problem is that getJSON is asynchronous.
while(params) executes. It's truthy, so we continue
$.getJSON is called. The function passed to it will not be called at this time. It's just queued to the subsystem that later will perform the actual request - asynchronously.
while(params) executes again. The callback passed to getJSON has not gotten a chance to run yet, so params is unchanged.
Go to step 2.
In other words, you created an infinite loop, since the system that processes the queued callback function never gets to execute because of the infinite loop. All you end up doing is creating a infinitely long list of queued getJSON calls.
A better solution would be something like this:
function sendRequest(params) {
$.getJSON("url", params, function(data) {
if(data contains something important)
params.foo = bar;
sendRequest(params);
else
params = null;
// Probably do something like requestChainFinished(params);
});
}
sendRequest({param1:'value', param2:'value'});
By using a function, you take control of the flow and don't perform another request until the asynchronous callback to getJSON has been called.
'params' is a closure variable. The value of params changes at a later time in the callback when the asynchronous ajax call's response arrives, but your while loop is keeping the JS engine busy that the callback isn't going to get called ever.
Either you could keep calling the same function in the response callback or you can use async: false like this $.ajax({ async: false, ...
I am very new to JavaScript and need to use callback function in my java script function. I don't know how to use a callback function. Below is my code:
function SelectedFeature() {
// Here is my code call_Method1();
call_Method2();
}
The problem in the above function is that, call_method2() starts executing before call_Method1() ends its execution. To solve this problem, someone told me to use a callback function. Now how can I use callback function in my SelectedFeature() function? Please explain by using code sample.
I'm making an asynchronous request in call_method1(). I need call_Method2() should be called after completing execution call_method1(). But in my case, call_method2() calls before call_method1() completes its execution. Now how can I fix this?
You have to refactor call_method1() to accept and execute a callback after it finished execution:
call_method1(call_method2);
and
function call_method1(callback) {
// ...
// do asynchronous stuff, when the response is processed, call
if(typeof callback === 'function') {
callback();
}
// ...
}
Functions are first class citizens, so by referring to them by their name, you can pass them around like any other value.
We could help better if you post the code for call_method1.
What are you using to do your asynchronous call? Did you code it yourself or are you using a library like JQuery?
You could simply put a bool to say "working" that you set to true as method 1 starts and back to false when it finishes. you could then have method2 wait while working is true.
The question has already been answered above by Felix. Inspired by his answer and an issue I am having in a current project, I wrote a little gist that has a class that adds up a little extra safety.
To sum up, you pass a callback function just as the way you pass a variable. Then the receiver will trigger it as a function.
myCoolFunction: function( data ) {
// Do some thing with response
}
$.get( '/some/cool/url', myCoolFunction );
In the above $.get calls back myCoolFunction with the parameter data once the data is fetched
What happens if myCoolFunciton is a variable. Well it depends on how the receiver handles the input.
Just to be careful, I have a CoffeeScript class ( and its JavaScript compilation ) that will do some safety checks.
It doesn't do any thing magic, checks if its a function and returns, if not returns an empty function so that it would reduce possibility of JS error. https://gist.github.com/ziyan-junaideen/8717925