Why does Javascript need an anonymous function to delay execution? - javascript

In my application I need to conduct an IP lookup as a prerequisite to proceeding with execution of another function that needs that data. Originally, I called the function as follows:
$(document).ready(function(){
var ipUrl = "myURL?callback=?";
$.getJSON(ipUrl, function(data) {
window.ip = data['ip'];
console.log("inside function" + window.ip);
}).done(printIp());
});
function printIp() {
console.log("function is done " + window.ip);
}
However, this outputs as
function is done undefined
inside function <ip_address>
I.e. the printIp() function is called before the $.getJSON is actually complete.
If however, I wrap the printIp() call within an anonymous function as follows:
$.getJSON(ipUrl, function(data) {
window.ip = data['ip'];
console.log("inside function" + window.ip);
}).done(function() {
printIp();
});
I get:
inside function <ip_address>
function is done <ip_address>
As I would expect. What is going on here? Why do I need to wrap the function call in an anonymous function?

your code says
}).done(printIp());
what this does is calling printIp and using the result of the function call as an argument to the done method.
what you actually want is passing the function as a done handler. use }).done(printIp); to do this instead.

You are executing printIp right away. Try it without the ():
$.getJSON(ipUrl, function(data) {
window.ip = data['ip'];
console.log("inside function" + window.ip);
}).done(printIp);

pass the function without parantheses, otherwise you are calling it right away:
.done(printIp)

Related

JS - Calling function from function not working

I have a function that gets called, and in it, I call another function called:
updatePerson(name)
For some reason it never activates when the function below is called. Everything else in the function works.
function updateName(name) {
$.get('XXX',function (data) {
var results = $.parseJSON(data);
var matchName = String(results.data[0].first_name);
updatePerson(matchName);}
);
};
Has anyone got an idea what I am doing wrong?
If I run alert(matchName) I get Nick as a response.
If I run console.log(updateMap(matchAddress)) I get undefined
It could do with the fact that you're passing a parameter from a callback function. In Javascript, variables inside a Callback are not available outside the callback.
Try setting the value of String(results.data[0].first_name) to a variable declared outside of the updateName function (i.e a global variable) and then call the updatePerson function outside of update name, with the globally declared variable as a parameter. Like so
var globalMatchName = '';
function updateName(name) {
$.get('XXX',function (data) {
var results = $.parseJSON(data);
globalMatchName =String(results.data[0].first_name);
}
);
updatePerson(globalMatchName)
}

How to make JS function wait for JSON data to load?

This works:
function getDataJSON() {
var queryString = "https://www.examplesite.com/someJSON.json";
$.getJSON(queryString, function(data) {
doStuffWithData(data)
});
}
function doStuffWithData(JSON) {
// some code that refers to JSON
}
getDataJSON();
But this complains that a variable (JSON) is undefined somewhere in doStuffWithData():
function getDataJSON(callback) {
// Gets share data and runs callback when received
var queryString = "https://www.examplesite.com/someJSON.json";
$.getJSON(queryString, function(data) {
if(typeof callback === "function") {
callback(data);
}
});
}
function doStuffWithData(JSON) {
// some code that refers to JSON
}
getDataJSON(doStuffWithData());
What am I likely to be doing wrong? The $.getJSON() call takes a second or two so I do need to wait for that and do stuff after it. I think the issue is with the code execution order, but it could be that I've misunderstood how to properly pass the data to the callback function.
It would be better if I could just load the data into a variable all my other functions can access.
This:
getDataJSON(doStuffWithData());
should be this:
getDataJSON(doStuffWithData);
Otherwise it invoked that function immediately and attempts to pass the result of the function into getDataJSON
You need to leave out the parenthesis in this call
getDataJSON(doStuffWithData()); should be getDataJSON(doStuffWithData). The reason is that doStuffWithData is the function and doStuffWithData() is the retrun value from the function.

Listen for a function to be called JavaScript

I have the following functions that is called every 2 seconds to load some data. It registers the function [do] to do the stuff with the response. (the example is simplified).
function doRequest (){
$.ajax({ url: 'www.google.com.pe', success: function (response) {do(response)} });
}
function do (text){
var i = setInterval(doRequest, 2000);
}
I wonder if there is any way that I can create a function that is called every time the [do] function is called with out needing to add a call to the listener inside the do function. If there is any better way to do it with jQuery, like a plugin I'd appreciate the help.
[Edit] The idea is not whether it works or not. My question was about if I can add a custom listener to the "do" function which was already implemented. Something like addActionListener("do", "after", doSomeThingElse),sSo I could do some thing else just after the do function has finished.
First, your simplified version won't work, because you'd need to pass the do function instead of calling it.
function doRequest (){
$.ajax({ url: 'www.google.com.pe', success: _do });
}
But it sounds like you're asking how to run some other code every time do is invoked.
If do is only invoked inside the doRequest() function, then just add your other code to an anonymous function that invokes do at the right time.
function doRequest (){
$.ajax({ url: 'www.google.com.pe', success: function(response) {
// Run your other code
// or invoke another function.
_do(response);
} });
}
If you want it to be more generalized, you can create a function decorator that returns a function which invokes do after some other code.
function doFactory(fn) {
return function() {
fn.apply(this, arguments);
_do.apply(this, arguments);
}
}
then make functions like this:
var doFoo = doFactory(function() {
console.log("foo");
});
If your requirement is more specific of a pre-processing of response, you could rework it like this:
function doFactory(fn) {
return function(response) {
_do.call(this, fn.call(this, response));
}
}
Then have the fn manipulate and return response.
var doFoo = doFactory(function(response) {
return response + "foo";
});
If you want to keep existing code as it is, you could wrap do() in another function which in turn calls do() and your new function (say do_this_as_well()).
See the example below (I renamed do() to do_this() to avoid confusion around the reserved keyword do). This works because global functions are nothing but variables with function objects in them. These variables can be overwritten, in this case with a new function that calls the old one:
function do_this(response) { ... }
(function()
{
var previous=do_this;
do_this=function(response) { previous(response); do_this_as_well(); }
})();
Replace
success: do(response)
with
success: function(response) { do(response); do_this_as_well(); }

Javascript callback functions execution

I'm not sure the correct term for this. But I want to write a function that accepts another function and execute it.
For eg.
function test(data, aFunc) {
var newData = data + " Shawn";
aFunc.call(newData);
}
test("hello", function(data){
alert(data);
});
Data is supposed to contain "hello Shawn" string. Help me rewrite this the correct way please.
The first argument of the call method is used to set the this keyword (the function context) explicitly, inside the invoked function, e.g.:
function test(data, aFunc) {
var newData = data + " Shawn";
aFunc.call(newData);
}
test("hello", function () {
alert(this); // hello Shawn
});
If you want to invoke a function without caring about the context (the this keyword), you can invoke it directly without call:
function test(data, aFunc) {
var newData = data + " Shawn";
aFunc(newData); // or aFunc.call(null, newData);
}
test("hello", function (data) {
alert(data);
});
Note that if you simply invoke a function like aFunc(newData); or you use the call or apply methods with the this argument set as null or undefined, the this keyword inside the invoked function will refer to the Global object (window).
Looks fine but you can just change
aFunc.call(newData);
to
aFunc(newData);
You were close. The first argument to "call" is the "scope" argument. In this case, it doesn't matter what it is, because you're not using "this" anywhere in your anonymous function, so any value will suffice.
function test(data, aFunc) {
var newData = data + " Shawn";
aFunc.call(this, newData);
}
test("hello", function(data){
alert(data);
});

calling a javascript function (in original function) from called function?

Is there anyway to calling a function from another function .. little hard to explain. heres in example. One function loads html page and when ready it calls the original function.
I think i need to pass in a reference but unsure how to do this... if i set it to "this" - it doesn't seem to work
ANy ideas?
order.prototype.printMe = function(){
order_resume.loadthis("myTestPage.html", "showData");
}
order.prototype.testme= function(){
alert("i have been called");
}
//Then when in "loadthis" need to call
orderRsume.prototype.loadthis= function(){
// DO SOME STUFF AND WHEN LOADS IT ARRIVES IN OnReady
}
order.prototype.OnReady= function(){
/// NEED TO CALL ORIGINAL "testme" in other function
}
It's not clear for me what you really want to do. In JS functions are first-class objects. So, you can pass function as a parameter to another function:
Cook("lobster",
"water",
function(x) { alert("pot " + x); });
order.somefunc = function(){
// do stuff
}
order.anotherone = function(func){
// do stuff and call function func
func();
}
order.anotherone(order.somefunc);
And if you need to refer to unnamed function from it's body, following syntax should work:
order.recursivefunc = function f(){
// you can use f only in this scope, afaik
f();
};
I slightly changed the signature of your loadthis function aloowing it to be passed the order to actually load.
I also assumed that your doSomeStuff function accepts a callback function. I assumed that it may be an AJAX call so this would be trivial to call a callback function at the end of the AJAX call. Comment this answer if you need more info on how to fire this callback function from your AJAX call.
order.prototype.printMe = function(){
order_resume.load(this, "myTestPage.html", "showData");
}
order.prototype.testme= function(){
alert("i have been called");
}
//Then when in "loadthis" need to call
orderRsume.prototype.load = function(order, page, action){
// DO SOME STUFF AND WHEN LOADS IT ARRIVES IN OnReady
doSomeStuff(page, action, function()
{
order.OnReady();
});
}
order.prototype.OnReady= function(){
/// NEED TO CALL ORIGINAL "testme" in other function
this.testme();
}

Categories