I have 2 javascript functions, the first being a function which loads ajax content (via another function), and a second which is a callback function. They look like:
function createReply(callBack){
ajaxPage('test.html', 'next-reply');
callBack();
}
function updateNext(){
document.getElementById('next-reply').id = "reply-item";
}
createReply(updateNext);
As you can see, I am calling the createReply() function and passing it the name of the callback function, in this case updateNext()
In the createReply() function, I am calling another function which loads content via ajax. When this function is complete, the callback is supposed to be executed. The callback changes the id of the div in which the ajax content is being loaded. This is where the problem is occuring
I am getting the error:
Uncaught TypeError: Cannot set property 'innerHTML' of null
Which is saying that it cannot change the content of the element with the id "next-reply" because it doesn't exist, and the reason it doesn't exist is because the callback function changes the id if that element. The intention is to have the callback fire after the ajax content has been loaded (ie; after the ajaxPage() function has been executed)
Can anyone see what the problem is? Is there a better way of implementing a callback function in plain javascript?
PS: no jQuery
As pointed out in the comments, this is due to the fact that AJAX calls happen asynchronously. The thread that createReply runs in continues to run before a response is returned from the server.
You'll need to re-factor ajaxPage to accept a reference to callback, and call it when the response is ready. Something like:
function createReply(callBack){
ajaxPage('test.html', 'next-reply', callBack);
}
Then, in ajaxPage:
function ajaxPage(url, id, callback){
//Do AJAX stuff
//When the response is returned:
if(callback) callback();
}
Right now you callback is executed right after the ajaxPage function. By right after I mean you do not wait for ajaxPage to return success. It is fired right after the ajax call goes out. It is very likely that it is not completed before your callback is fired.
Related
Okay so look at these to alert()s. Here is the full code:
function OfficialFacebookLikes(Title)
{
$.getJSON('https://graph.facebook.com/'+Title, function(data) {
alert(data['likes'].toString()); //<<temp
return data['likes'].toString();
});
}
$(document).ready(function(){
$('.ui-btn').click(function(){ //cocacola
var LikeCount = OfficialFacebookLikes("cocacola");
alert(LikeCount);
});
});
Why does
alert(LikeCount)
display (which is "undefined" when displayed) before
alert(data['likes'].toString())
I called the function OfficialFacebookLikes before I called the alert(LikeCount). Could someone please explain why this is occurring. If my thought process isn't making since.. I'm use to coding in C++.
This is an asynchronous Ajax call. You won't have data available until the call returns. In your document ready code, you are attempting to alert the call immediately.
Instead, do whatever you need to do with the result set in the callback handler of the ajax:
$.getJSON('https://graph.facebook.com/'+Title, function(data) {
doSomethingWithMy(data);
});
The .getJSON function is asynchronous, this means that it needs a callback to call when it's finished, otherwise you'll never know when the function has been completed. Asynchronous functions run separately from the rest of the code.
When you call OfficialFacebookLikes("cocacola") it will call the .getJSON function. Now the .getJSON functions starts by its own and doesn't stop the script, so right after calling OfficialFacebookLikes("cocacola"), the next line of code is executed, which is actually alert(LikeCount). But LikeCount has not yet been defined, since that .getJSON is still working.
When .getJSON finishes working the callback function given in $.getJSON(..., function() {... }) gets executed, and then the LikeCount variable gets defined. So if you want to alert LikeCount you have to put the alert() inside the callback of .getJSON.
I am using jquery for ajax calls
All the calls are called immmediately on page load and we are getting the responses at almost the same time.
the issue is, the 3 calls are fired and I am getting the data, but the callback function is fired for the first call only.
the other two callbacks are not called, the callback is defined as a separate function,
If I just write an alert instead of calling the callback method, all the 3 alert message are coming
So the issue is when we write the callback method, do any one have any idea of the strange behaviour?
We tried to reorder the calls, the behaviour is similar, which ever is called first, its callback will be called, for the rest, it will not be called
var url = "/test1";
ajaxCall(url, testMethod1, false);
var url = "test2";
ajaxCall(url, testMethod2, false);
var url = "test3";
ajaxCall(url, testMethod3, false);
testMethod1:function(data){
console.log("first"+data);
},
testMethod2:function(data){
console.log("second"+data);
},
testMethod3:function(data){
console.log("thrid"+data);
}
ajaxCall is defined as jquery ajax, the issue is only the testMethod1 is called, the rest 2 are not called
Regards
Hari
Well the thing that immediately caught my eye is that the URL for test1 has a forward slash preceding test1. This means that you are using a valid link in only test1. The alerts will trigger because you are probably not trying to access the data returned (which would still work even though the ajax request fails), where as you are trying to access the data in the coded call back functions you have provided, which will obviously throw a NullPointerException or whatever the equivalent as the ajax call fails due to an incorrect URL. Therefore data never gets set and the code doesn't work.
I've a javascript method defined as follows:
updtCrtEdtPage = function() {PrimeFaces.ab({source:'j_id_ev',formId:'j_id_es',process:'typeNewLOB_in lobIdForEdit j_id_ev',update:'createLOBFullPagePanel',oncomplete:function(xhr,status,args){prepareForCrtEdtFullPage();},params:arguments[0]});}
I want to execute certain method (afterComplete()) whenever this method has finished executing. (This method actually initiates an ajax request & appends the received HTML data on the DOM). So I want my afterComplete() method to be executed whenever ajax response has been received.
I cannot directly do like:
updtCrtEdtPage();
afterComplete();
as this would call the afterComplete() soon after ajax request is initiated & not completely finished executing yet.
Is there any JS/ jQuery way I could do that ?
You could pass afterComplete as a parameter so your function can call it when the ajax call is complete. Something like this...
updtCrtEdtPage = function(callback) {
PrimeFaces.ab({
source:'j_id_ev',
formId:'j_id_es',
process:'typeNewLOB_in lobIdForEdit j_id_ev',
update:'createLOBFullPagePanel',
oncomplete:function(xhr,status,args){
prepareForCrtEdtFullPage();
callback();
},
params:arguments[0]
});
}
updtCrtEdtPage(afterComplete);
Since you say you can't modify updtCrtEdtPage, but you can modify prepareForCrtEdtFullPage I'd suggest using a global variable to determine which callback function to call when the method is complete...
updtCrtEdtPageCallback = afterComplete;
and then in prepareForCrtEdtFullPage just add the last line...
updtCrtEdtPageCallback();
The first method is tidier, but the second will suffice for your particular situation.
your updtCrtEdtPage = function() has an oncomplete callback which is called when the ajax response has been received, add your afterComplete function in that callback and it will execute after the ajax request has been completed.
oncomplete:function(xhr,status,args){
prepareForCrtEdtFullPage();
afterComplete()
}
I add a click event handler to an element
$(".elem").click(function(){
$.post("page.php".function(){
//code1
})
})
And then I trigger a click event
$(".elem").click();
//code2
How can i make sure that code2 executes after code1 executes
(Ignoring WebWorkers) JavaScript runs on a single thread, so you can be sure that code2 will always execute after code1.
Unless your code1 does something asynchronous like an Ajax call or a setTimeout(), in which case the triggered click handler will complete, then code2 will execute, then (eventually) the callback from the Ajax call (or setTimeout(), or whatever) will run.
EDIT: For your updated question, code2 will always execute before code1, because as I said above an async Ajax callback will happen later (even if the Ajax response is very fast, it won't call the callback until the current JS finishes).
"How i make sure that code2 executes after code1 executes"
Using .click() with no params is a shortcut to .trigger("click"), but if you actually call .trigger() explicitly you can provide additional parameters that will be passed to the handler, which lets you do this:
$(".elem").click(function(e, callback) {
$.post("page.php".function(){
//code1
if (typeof callback === "function")
callback();
});
});
$(".elem").trigger("click", function() {
// code 2 here
});
That is, within the click handler test whether a function has been passed in the callback parameter and if so call it. This means when the event occurs "naturally" there will be no callback, but when you trigger it programmatically and pass a function then that function will be executed. (Note that the parameter you pass with .trigger() doesn't have to be a function, it can be any type of data and you can pass more than one parameter, but for this purpose we want a function. See the .trigger() doco for more info.)
Demo: http://jsfiddle.net/nnnnnn/ZbRJ7/1/
You can try writing this way:
$(".elem").live("click", function(){
//code1
})
// for newer jquery version from 1.9
$(".elem").on("click", function(){
//code1
})
And, your trigger will always execute as fired.
Wrap code2 in method and add it as a callback inside code1 so it will always get called after code1 executes
code2 = function(){/*code2*/};
$(".elem").click(function(){
//code1
code2();
})
Javascript execution is line by line. So whatever comes up, will be executed first. So adding the click code before the other method will work.
Plus if there is any async call, then take a flag which is set only when you get response.
var clicked = false;
$('#elem').click(function(){
// do some async process
clicked = true;
});
while (!clicked){ // do nothing }
// other function to be called
Or the second option will be, if using post method, set async = true in property.
I'd like to fire a JavaScript function when AJAX returns the values of drop down items.
The scenario is:
function 1 fires -> ajax gets items from database -> the dropdown items are filles -> my javascript function is called.
Does any of you have idea how to make a handler for such event ?
As you've tagged the question with jQuery, I'll show you a jQuery solution:
$.post("someScript.php", function(data) {
/*This callback function is executed when the AJAX call returns successfully
You would do something with your dropdown items here
and then call your next function.*/
});
The various jQuery AJAX methods (post, get, load for example) all provide a way to pass a callback as an argument. The callback is executed upon a successful response from the server. Inside that callback function you can execute whatever code you need to, to deal with data which contains the response.
If you're not using jQuery, I'll assume you already have an XMLHttpRequest object. XMLHttpRequest has a property called onreadystatechange to which you can assign a function that runs when the state changes:
xhr.onreadystatechange = function(){
if(xhr.readyState == 4) {
//This will be reached if the call returns successfully
}
}
The idea is the same as the jQuery method shown above.