I'm experiencing some extremely weird behavior with Ajax. Or maybe it's normal. I wouldn't know. I'm quite new to playing around with Ajax.
My problem is that I am making a few Ajax calls(two using $.post() and one using the standard $ajax() call), and they seem to return the data fine, but the code inside the success function only works in a very peculiar way.
I have noticed that some things work if placed first in line to be executed; but why is that? It really doesn't make any sense to me. In this case I would like the span with the id link_span to be updated dynamically, as my Ajax calls link and unlink devices from each other.
(the correct_classes function counts how many links have been linked and adds it to the link_counter variable that I've made global with the window object).
But as the span only wants to update if the corresponding code is placed on top, it's kinda useless.
Another problem is also that .ajaxComplete() and other such event handlers don't always get called. For example, I attempted to show and hide a loader gif by using .ajaxComplete() to close it when ajax stop. But this only works with one of my calls which is the standard $.ajax call.
I'm really confused.
Any help would be great, and please ask me to clarify if there's something I haven't made clear enough.
Here is a small snippet of what I'm talking about:
$.post( "<?php echo base_url(); ?>connections/ajax_link", datax).done(function( resp,status ) {
$("#loader_overlay").css('display','none');
display_confirmbox();
resp=JSON.parse(resp);
var str = resp['parent_selector'];
var arr = mystr.toString().split("||");
correct_classes(arr[1], resp);
$( '#link_span' ).text( '( ' + window.link_counter + ' ) links found' ); //this doesnt work unless its on top
});
Update
It seems that the problem is caused by correct_classes();
the array from the ajax call gets passed to the function in which jQuery complains about something, and causes the rest of the ajax code to halt. Yet everything inside correct_classes() gets executed. The error in question is this:
TypeError: invalid 'in' operand e
specifically what is causing the problem seems to be this(i commented everything else out and this is:
$.each( val, function( i, value ) {
var mystr = value;
}
I really cant figure out why it complains about this code when it seems to work.
i'm not sure to have understand your problem.... but if you use 3 async ajax call ($.post or $.ajax is indifferent $.post is a contract syntax to call $.ajax({type:"post"})) you need to wait the full loading of all calls for use their response.
so.. if one of your call evalue window.link_counter you need to wait his response before call the code you have post.
For wait the complete load you may nast the call inside the success function of the prev call.
for you knowlage there is an attribute of $.post() dataType if you set it to "json" you not need to parse the response because Jquery do it for you, this code is useless:
resp=JSON.parse(resp);
and, the method .done() is calling whether the call is successful if it fails, $.post() has a success function callback. Use it, it's better, and use .fail() to catch call error.
See documentation about $.post(): here
however... the element who have this id #link_span is generated by one of ajax call?
Related
Hi I am running an AJAX Post to my PHP url and when done I am returning a document.ready function with my appended jQuery page.
I want to make sure if I am doing this correctly when placing the function in the success part of my AJAX post. It will not work at the minute. Any help would be great?
function loadJobRequests() {
/ /AJAX code to submit form.
$.ajax({
type: "POST",
url: "http://localhost:8888/EduSubOct/json-data-
jobrequests.php",
data: { userEmail: localStorage.getItem("email") },
cache: false,
success: function() {
$(document).ready(function(){
I just need to find out if i have to pass any parameters into the function at success and then same same parameter into document.ready. Thanks
Short answer: no, you shouldn't use $(document).ready(...) here. The function you put inside that is only executed at the moment the DOM is first "readied", shortly after page load - this will be long since past by the time your script has been loaded, executed, fired an Ajax call and then returned the response (all of which needs to happen before your success callback happens).
But the very reason that $(document).ready(...) doesn't work also means that you don't need it here. The only reason it's used is to make sure that any DOM elements you refer to (typically to attach event handlers to) actually exist and the point this code is executed. Since the "ready" event has long since fired by the time the Ajax response comes in, the DOM will accurately reflect the current content of the page, and you can safely do whatever you want to manipulate it.
So whatever function you were going to put inside there, just put directly in the success callback.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I apologize for asking such a simple question, but googling "javascript or jquery first" just keeps giving me people asking which they should learn first.
Currently I have a couple lines of javascript, followed by a bit of jquery, followed by a bit more javascript. This is the part where it breaks down...
$.get("alliances.php", function(data, status){
console.log(data);
searchIndex = data.search(allianceName);
rawAllianceLink = data.slice(searchIndex-25,searchIndex);
});
console.log(rawAllianceLink);
After I carry this code out, the JQuery goes last and my console.log prints undefined. (Note, the console.log isn't the actual statement, I have more lines that need to go after this, it is just an example that it is performed out of order.) Was wondering if someone could clarify or explain how I can alter when each of these steps is carried out.
Simple ans:
Its simply because your $.get(... is an AJAX call. You have to log your data in callback handler.
$.get("alliances.php", function(data, status){
console.log(data);
searchIndex = data.search(allianceName);
rawAllianceLink = data.slice(searchIndex-25,searchIndex);
})
.done(function() {
console.log(rawAllianceLink);
});
Let's get a few things clear here. $.get() is a wrapper for $.ajax() in jQuery. The javascript being applied happens within the jQuery library.
Next, the $.get call is asynchronous meaning that the console.log(rawAllianceLink); likely will fire prior to the $.get() request completing, which takes some time to fetch the file and read the data.
The function(data, status) is applied to the data returned from alliances.php only after the request has fully completed. Within that callback function, it would seem as if you've properly applied the javascript methods that you intend.
If you need to fire further code after the callback execution occurs, then you should place it into a function and execute the function at the end, passing the rawAllianceLink as an argument, like so:
$.get("alliances.php", function(data, status){
console.log(data);
searchIndex = data.search(allianceName);
rawAllianceLink = data.slice(searchIndex-25,searchIndex);
process_request(rawAllianceLink);
});
function process_request(RAL){
console.log(RAL);
}
Now things will be fired in the proper order. You could also look into jQuery's $.defered, but that may be another beast, entirely.
What is happening in your code, is that, the jQuery "get" function is called, which sends a request to the server to retrieve some information at "alliances.php", but it just sends the request, it doesn't wait for a response, then it carries on with the console.log. At some later point, the browser gets the response back from the server, and when the browser gets a chance, it executes the code in the callback function. This kind of programming isn't unique to jQuery, it happens with event handler, timeouts, intervals, etc. in javascript, whether you use jQuery or not.
Here is the code :-
var quiz;
function startQuiz() {
$.ajax({
url: 'get_quiz/',
cache: 'false',
dataType: 'json',
async: 'false',
success: function(data) {
quiz = data;
alert(quiz[0].q); // I'm able to access quiz here
},
}
);
}
startQuiz();
alert(quiz[0].q); // Not able to access it here.
I'm not able to access quiz here, am I mission something?, Whats wrong with this?
Ajax is assynchronous which can be an unfamiliar concept. Your code will run like this:
1. var quiz;
2. define function startQuiz;
3. call startQuiz;
4. do ajax call (and continue! don't block)
5. alert(quiz[0].q); // Not able to access it here.
-- ajax call comes back
6. quiz = data;
7. alert(quiz[0].q); // I'm able to access quiz here
Ajax is asynchronous, it doesn't block. This means that when you make the ajax call the callback doesn't actually get called until the ajax call returns, it doesn't block and wait. Instead the code will continue on.
Then later when the ajax call returns the data, your callback function will be executed.
Javascript does this by means of an event loop.
See it like this: steps 1-5 are part of the first event. 6-7 are part of the second event.
A cool thing about JavaScript is that in your callback you still have access to anything above it (like the variable quiz) because of scoping. This is called a closure. Your callback function closes around the scope and brings it with him to the next event.
AJAX calls are asynchronous, you should wait for the result to come back from the server. Either do all the work in a callback function or have a look on a promises library (I like Q promises library), which makes waiting for AJAX results very easy.
This is due to the asynchronous nature of JavaScript, once you call startQuiz() it executes and jumps back out and executes your quiz alert().
You have to access your quiz data explicitly after the callback is called to make sure you have access to it.
You also have to worry about scoping, as you may not be actually modifying the same quiz variable.
var quiz,
fetched = false;
$.ajax({
//blah
success : function(data){
fetched = true;
quiz = data;
}
});
setInterval(function(){
if(fetched){
//quiz is populated
}else{
//quiz hasn't be populated yet
}
},50);
Although not a clever example, I'm just trying to get the point across that startQuiz() doesn't wait for the ajax call. The A in AJAX mean asynchronous.
You should give jQuery deferreds a try which ist the preferred way of writing ajax related code since jQuery 1.5: http://javascriptplayground.com/blog/2012/04/jquery-deferreds-tutorial
Once you get the hang of it maybe will be easier to write and understand your code.
I have tested this on Firefox, Opera and Seamonkey. It works fine. When it comes to Internet Explorer 7. It works but upto a certain point. I am making an AJAX call to a PHP script every few seconds. In IE7 it makes the first AJAX call and it retrieves the data but it doesn't do it again ever. Even though i have a setTimeout function in the else block. WHY? :(
startTime = setTimeout('getStatus()', 5000);
}//function convertNow
function getStatus()
{
$.ajax({
type: "GET",
url: "fileReader.php",
data: 'textFile=' + fileNameTxt,
success: function(respomse){
textFileResponse = respomse.split(" ");
$("#done").html("Downloading & Converting Video...<b style='font-size:17px;color:green;'>" + textFileResponse[0] + "</b><br /><b>" + properFileName + '</b>');
}
});//ajax
if(textFileResponse[0]=='100.0%'){
}
else{
continueTime = setTimeout('getStatus();', 3000);
alert('call end');
}
}
Apologies if any frustration comes through this question. I've been running around like a headless chicken for the past 3 hours.
Thank you for any help.
EDIT 2
I have added the full function. The setTimeout seems to be working correctly. It must be the AJAX call, am just checking what is being returned. Even stranger! It keeps returning the same value from the AJAX request and its not getting any newer values!! I think Answer 2 might have something.It may be due with cache but how do you over come that?
Are you requesting the ajax call via HTTP GET as opposed to HTTP POST? IE tends to use cached results of ajax calls unless you use POST instead of GET.
EDIT: Since you've updated your question, I can see that you are indeed using the GET verb. Change it to POST and I bet your issue will be resolved.
You could still use the GET request and simply add
cache: false
to the $.ajax request.
Not at all sure on this but are you missing the ;?
from:
setTimeout('getStatus()', 3000);
to:
setTimeout('getStatus();', 3000);
I noticed that textFileResponse is set in the function declaration of the success handler for the AJAX call yet referenced as an array immediately after making the AJAX call. Perhaps in IE 7 the success handler hasn't completed before the array reference which would throw a java script error, thus the setTimeout would never run.
Here's a very simple Prototype example.
All it does is, on window load, an ajax call which sticks some html into a div.
<html>
<head>
<script type="text/javascript" src="scriptaculous/lib/prototype.js"></script>
<script type="text/javascript">
Event.observe(window, 'load', function(){
new Ajax.Request('get-table.php', {
method: 'get',
onSuccess: function(response){
$('content').innerHTML = response.responseText;
//At this call, the div has HTML in it
click1();
},
onFailure: function(){
alert('Fail!');
}
});
//At this call, the div is empty
click1();
});
function click1(){if($('content').innerHTML){alert('Found content');}else{alert('Empty div');}}
</script>
</head>
<body><div id="content"></div></body>
</html>
The thing that's confusing is the context in which Prototype understands that the div actually has stuff in it.
If you look at the onSuccess part of the ajax call, you'll see that at that point $('content').innerHTML has stuff in it.
However when I check $('content').innerHTML right after the ajax call, it appears to be empty.
This has to be some fundamental misunderstanding on my part. Anyone care to explain it to me?
Edit
I just want to clarify something. I realize that the Ajax call is asynchronous.
Here's the actual order that things are being executed and why it's confusing to me:
The page loads.
The Ajax request to get-table.php is made.
The call to click1() INSIDE onSuccess happens. I see an alert that the div has content.
The call to click1() AFTER the Ajax call happens. I see an alert that the div is empty.
So it's like the code is executing in the order it's written but the DOM is not updating in the same order.
Edit 2
So the short answer is that putting the code in onSuccess is the correct place.
Another case to consider is the one where you do an Ajax call and then do another Ajax call from the onSuccess of the first call like this:
new Ajax.Request('foo.php',{
method: 'get',
onSuccess: function(response){
doAnotherAjaxCall();
}
});
function doAnotherAjaxCall(){
new Ajax.Request('foo.php',{
method: 'get',
onSuccess: function(response){
//Anything that needs to happen AFTER the call to doAnotherAjaxCall() above
//needs to happen here!
}
});
}
The first letter of AJAX stands for "asynchronous". This means that the AJAX call is performed in the background, i.e. the AJAX request call immediately returns. This means that the code immediately after it is normally actually executed before the onSuccess handler gets called (and before the AJAX request has even finished).
Taking into account your edited question: in some browsers (e.g. Firefox), alert boxes are not as modal as you might think. Asynchronous code may pop up an alert box even if another one is already open. In that case, the newer alert box (the one from the asynchronous code) gets displayed on top of the older one. This creates the illusion that the asynchronous code got executed first.
Without having tried your code: The AJAX call is executed asynchronously. Meaning that your Ajax.Request fires, then goes on to the click1() call that tells you the div is empty. At some point after that the Ajax request is finished and content is actually put into the div. At this point the onSuccess function is executed and you get the content you expected.
It's Ajax call, which is asynchronous. That means right after that request call, response hasn't come back yet, that's why $('content') is still empty.
The onSuccess element of the function call you are making to handle the AJAX call is executed at the time you receive a response from get-table.php. This is a separate Javascript function which you are telling the browser to call when you get an answer from get-table.php. The code below your AJAX.Request call is accessed as soon as the AJAX.Request call is made, but not necessarily before get-table.php is called. So yes I think there is a bit of a fundamental misunderstanding of how AJAX works, likely due to using a library to hide the details.