i have a question regarding partial page loading with AJAX.
Suppose that an user clicks on a button that makes an AJAX call to load part of a page (it can possibly include dynamically loaded JS and/or CSS), and the html content is dropped on some div. Then, before the first load is complete he clicks on another button that makes another AJAX call that drops other content on the same div. How should i prevent this behaviour to create any conflicts? Some possible conflicts might be something like, for example, the first load executes some JS on content that is not found because the second load already changed that div.
Thanks in advance.
Edit:
I would appreciate answers based on asynchronous methods. Thanks.
Genesis and Gaurav are right about disabling user interaction. +1 from me to each of them. How you handle the logic is actually quite simple:
$('#my_submit_button').click(function(){
$.ajax({
url:'/my_file.php',
dataType='json',
beforeSend:function(){
$('#my_submit_button').prop('disabled',true);
},
error: function(jqXHR, status, error){
// handle status for each: "timeout", "error", "abort", and "parsererror"
// Show submit button again:
$('#my_ajax_container').html('Oops we had a hiccup: ' + status);
$('#my_submit_button').prop('disabled',false);
},
success:function(data){
$('#my_ajax_container').html(data);
$('#my_submit_button').prop('disabled',false);
}
});
});
make it synchronous (not recommended)
disable link/button while ajaxing
do not mind about it
but in your case it won't do any conflicts because when html is replaced, scripts too
Just disable the buttons that cause the AJAX calls to start while one has not completed yet.
I'm not sure this would actually be a problem for you because Javascript is single threaded. When the first ajax response comes in and you execute some javascript, that javascript cannot be interupted by the second ajax response as long as it is one continuous thread of execution (no timers or other asynchronous ajax calls as part of it's processing).
Let's run through a scenario:
User clicks button - first ajax call starts.
User clicks button - second ajax call starts.
First ajax call finishes and the completion code execution starts for what to do with the new data.
While code is executing from first ajax call, the second ajax call completes. At this point, the browser puts the second ajax call completion into a queue. It cannot trigger any of your completion code yet because the Javascript engine is still running from the first load.
Now the first load completes it's execution and code and returns from it's completion handler.
The browser now goes to it's queue and finds the next event to process. It finds the completion of the second ajax call and then starts the completion code for that ajax call.
As you can see from this scenario which has overlapping ajax calls and the second completing in the middle of the processing the first, there still is no conflict because the Javascript engine is single threaded.
Now, as the other answers have suggested, you make not want this user experience of launching a new request while one is still processing, but they won't technically conflict with each other. You have several tools you can choose from if you want to prevent overlapping calls:
You can prevent starting the second call while the first call is unfinished. You can do this both in the UI and in the actual code.
When there are multiple calls outstanding, you can decide to drop/ignore the earlier responses and not process them - waiting only for the last response.
When the second call is initiated, you can cancel the first call.
You can let the second just replace the first as in the above scenario.
The first two options require you to keep track of some cross ajax-call state so one ajax call can know whether there are others and act accordingly.
Related
I am working on a CRM we inherited. Long story short - there is a button that calls a php script which should run in background and we don't need to wait for response.
request(idata+'transferInTimeExec.php',{
sync: false,
preventCache:true,
method:'GET'
});
Now, the transferInTimeExec.php takes an hour to run, it's a very complex script that deals with weekly timesheets for a recruitment company, processes them, does a lot of DB operations etc.
Using Chrome. Every time I press the button to run it, it blocks all the xhr calls until it finishes. CRM is "ajax heavy" and while the script is running, the user can't do anything, if they navigate to another subpage, no xhr requests will resolve until that process we started has finished. Even when I open a new browser tab and try to do something, it won't do it. If I open the CRM in another browser (Firefox) while the script is running, I can use the CRM.
In Network tab - the first one is pending, and as you can see all the subsequential calls to a different Ajax call wait (all have sync:false)
I even replaced the whole logic with PHP function sleep(30) to make it just do nothing for 30 seconds before returning anything - same issue.
I tried XHR in plain javascript, inside onClick on the button HTML markup, rather than Dojo methods - same issue.
I've done a brutal Search/Replace on the whole project, replacing sync:true to sync:false - nothing changed.
I have run out of ideas, maybe anyone here can help to figure this out? Is there a global switch for sync/async? What else could it be if not ajax issue?
Your script transferInTimeExec.php is probably using session. When thats the case, other AJAX Call would not initiate and instead wait for this AJAX Call to Finish so as to not overwrite the session data. Setting AJAX call to asynchronous does not change the behavior.
If this script takes 1 hour to run it is a bad idea to call it as an AJAX from UI. You should setup a Cron, hourly or daily, and perform all the operations in the backend. Of course, you will need to make some adjustment to the script if it is using session.
EDIT
You could use session_write_close(); at the top of your script. This tells the PHP that this script would not write anything to the Session so other AJAX Calls are free to use the Session. However be careful to not write anything to Session after this as this will result in an error.
Javascript is said to be single-threaded. Also AJAX is said to be asynchronous.
Consider a scenario;
I have a button and on click of it, I make a AJAX call which takes 5-6 seconds. Now the UI would not be blocked and the user does some other action (say click on another button which is now executing some code, while the AJAX response has been returned). Now in this case, since the other code is being executed, when would the AJAX callback be executed? Would it have to wait OR can it be executed in a parallel thread ?
The events are queued, so when the Ajax call completes, the handler for that would be queued to run on the event loop. When the single thread is done with your button handler, it'll then process the next event in the queue. So - you would have to wait for the code kicked off by the button click to finish, unless of course the Ajax request completed before the user clicked on the button, in which case the button click handler had to wait. The best you can do is split up your algorithm so that it runs in discrete chunks, these can be dropped onto the queue using setTimeout, but that is quite tricky.
So I have searched a little about this topic in general. Contrary to what I have imagined, javascript is nothing like multi-threaded. Instead, it has a queue of operations it performs.
The direct answer then is: Depending on the very exact timing, the AJAX callback might have to wait before click event completes. It also might have to wait for any other code that was executed at "the same moment".
This explains while things like while(true) or alert() stop every script on the site.
Can anybody pls tell me, how can i make a AJAX request and send user to some other page when he performs following actions ?
Clicks on next, prev btns of browser.
refresh page by any way(f5,ctrl+r,refresh btn).
try to close browser's window(Here i don't want to redirect him, just AJAX request).
i thought window.onbeforeunload could make it,
window.onbeforeunload = function () {
makeAjaxCall();
------
------
}
// Ajax Call is successful
function makeAjaxCall_SuccessHandler() {
window.location.href = 'Home.html';
}
but it is not working at all........
after searching on this topic i found that this is a kind of rule made for browser's security.
so pls tell me how to do this or any alternate way to achieve this.
You're not describing the actual behavior you're getting so I'm kinda guessing here, but I think your problem here is with the Asynchronous part of AJAX.
You see, when your onbeforeunload handler executes it may very well initiate the AJAX call BUT it won't block waiting for its results to return. Instead the execution will continue and onbeforeunload will complete before you ever get any result from your AJAX request (if any call is made at all).
First of all add some debug traces to validate your handler is actually executed. If it is, add an idle loop to keep it busy (preventing it from returning) and see if the AJAX call comes through (I'd check the server side for that).
If that's indeed the case I guess you'll have to modify the idle loop to consult some kind of flag. Or even better, if the libraries you use allow it, make the server call synchronous.
I think no.
Browsers can stop execution at any time after action. Ajax call is very long operation for this.
With onbeforeunload you can asking user questions like "Are use sure?". You must return string or assign it to event.returnValue
You can read about it here https://developer.mozilla.org/en/DOM/window.onbeforeunload
I think with your problem you can try to make synchroness call or try to open iframe with some GET parameter or send form data in iframe in body of this function. But i don't sure about time.
I'm doing some YouTube related stuff in a UIWebView on iOS. I'm using the mobile version of YouTube and they load things in the absolute strangest way (they make a bunch of AJAX calls to actually load the page while only loading basically a template first).
Something else strange: I'm logging the entire body of the page with this:
NSLog([webView stringByEvaluatingJavaScriptFromString:#"document.documentElement.innerHTML"]);
What's strange is that the logging doesn't happen until all AJAX is finished and the page is loaded. But I'd always thought that JavaScript doesn't wait for AJAX to finish before proceeding to execute the next line of code - this is contradicting that; it's actually waiting for AJAX to complete then returning the true, complete HTML of the page.
Any help? I'm confused.
XMLHttpRequests aren't necessarily asynchronous.
If we assume your AJAX is asynchronous, the page load order could affect what you're seeing.
Script tags in are executed first. The body is not available.
Script placed between are executed as they are encountered during page load, body is available up until the point the script is.
When all resources are loaded window.onload event is executed.
So depending on where your AJAX calls and where your logging call is this could affect the order you are seeing things.
Then depending on the finer implementation details of NSLog(), you may not see the output from a logging statement the very instant you are calling it. Many times there are buffers which are flushed now and then - perhaps only when the UI thread is not busy doing anything else.
I have a web page and I am associating a note with the page storing it in my database, so that the whenever the next time the page is loaded that notice can been seen till it is deleted by some other user authorized to do the same. However, say I associate a note with the page after some content is loaded through AJAX. I want the note to appear only after that particular content has loaded next time on the web page. I would like to track the AJAX request and attach the note to it? I want to do it all through simple JavaScript code put at the bottom of any web page. How can it be done?
jQuery ajax provides methods to fire events before, during and after the ajax request. Please check the api here for complete list.
Here are couple of methods that are called after completion of every ajax request.
jQuery.ajaxComplete() - Register a handler to be called when Ajax requests complete.
jQuery.ajaxSuccess() - Show a message when an Ajax request completes successfully
These functions allows you to pass a callback function to trigger after event occurs. In that call back function check if content you want is loaded or not, then show the note.
Sample code for the above methods can be found here:
http://api.jquery.com/ajaxComplete/
http://api.jquery.com/category/ajax/
Hope this helps.
You'd need to write a wrapper for all of your ajax calls that checks the result and sees if it should add a note. Here's an example, assuming you're using jQuery to handle the ajax requests:
function ajaxWrapper(settings){
var old_callback = settings.complete;
settings.complete = function(request, status){
if(status == "200"){
// check the request.responseText and add your note if appropriate
}
if(old_callback){
old_callback(request, status);
}
}
jQuery.ajax(settings);
}
And then instead of calling jQuery.ajax() directly, call ajaxWrapper() instead.
An alternate option would be to include the note in your ajax response.