given to certain circumstances, I'm forced to keep page settings (Javascript-values) in the session and it has to be done right before leaving the page (I can't use cookies, since "pageSettings" can become quite large and localStorage is not an option yet ;) ). So this is how I tried it. However it seems that when I call the page directly again, the call of "http://blabla.com/bla" happens asynchronous, even though the async-attribute is set (I don't receive the settings of the previous call, but of the one before):
$jQ(document).ready(function () {
$jQ(window).unload(Main.__setSessionValues);
});
var Main = {
pageSettings: {},
__setSessionValues: function __setSessionValues() {
$jQ.ajax({
type: "POST",
async: false,
url: "http://blabla.com/bla",
data: {
pageSettings: Object.toJSON(Main.pageSettings)
}
});
}
};
Does anyone know what the problem might be?
thanks in advance
The code looks fine. You might try bind('beforeunload', ...) rather than unload, to grab things as early as possible. But of course, if something else also hooks beforeunload and the unload gets cancelled, your call will have been made even though you're still on the page.
Slightly off-topic, but if you can possibly find a different way to do this, I would. Firing off synchronous ajax calls when the user is trying to leave the page is not ideal.
Related
I'm mainly asking this to know what's the best practice with regards to getting small data from the server.
Like for one example, I'm using an ajax(or sjax. lol) call to check if there are new Notifications for a user
function checkNewNotifs() {
$.ajax({
url: '/Home/CheckNewNotifications',
async: false,
success: function (data) {
if (data == 'True') {
$('#alert-icon').css('color', '#FF4136');
}
}
})
}
It gets the job done, but I'm thinking if there's a better way of achieving this?
I'm mainly using ASP.NET MVC 4/5 as of the moment to provide context.
Edit:
For the future ajax beginner readers like myself, the proper way of achieving something similar to this is through .done() I haven't completely grasped the idea of ajax yet, but a lot can be done through the following call:
function checkNewNotifs() {
$.when(
$.ajax({
url: '/Home/CheckNewNotifications',
success: function (data) {
//do data manipulation and stuff.
}
})).done(function() {
//append to view
})
}
tl;dr async: false = bad
The main reason why you should avoid sync request**s is a **hang outs of UI.
Is there a reason why do you use sync requests?
I think you should use async requests to check notifications, because in case when request will take a bit more time than you expect - user will not see any freezing of UI.
Especially this problem will be actual for users with slow internet connection or slow connection to your server (different country, or event different continent).
How can I fix the script below so that it will work EVERY TIME! Sometimes it works and sometimes it doesn't. Pro JQuery explains what causes this, but it doesn't talk about how to fix it. I am almost positive it has to do with the ajax ready state but I have no clue how to write it. The web shows about 99 different ways to write ajax and JQuery, its a bit overwhelming.
My goal is to create an HTML shell that can be filled with text from server based text files. For example: Let's say there is a text file on the server named AG and its contents is PF: PF-01, PF-02, PF-03, etc.. I want to pull this information and populate the HTML DOM before it is seen by the user. A was ##!#$*& golden with PHP, then found out my host has fopen() shut off. So here I am.
Thanks for you help.
JS - plantSeed.js
var pageExecute = {
fileContents:"Null",
pagePrefix:"Null",
slides:"Null",
init:function () {
$.ajax({
url: "./seeds/Ag.txt",
success: function (data){
pageExecute.fileContents = data;
}
});
}
};
HTML - HEAD
<script type="text/javascript">
pageExecute.init();
</script>
HTML - BODY
<script type="text/javascript"> alert(pageExecute.fileContents); </script>
Try this:
var pageExecute = {
fileContents:"Null",
pagePrefix:"Null",
slides:"Null",
init: function () {
$.ajax({
url: "./seeds/Ag.txt",
async: false,
success: function (data){
pageExecute.fileContents = data;
}
});
}
};
Try this:
HTML:
<div id="target"></div>
JavaScript:
$(function(){
$( "#target" ).load( "pathToYourFile" );
});
In my example, the div will be filled with the file contents. Take a look at jQuery .load() function.
The "pathToYourFile" cand be any resource that contains the data you want to be loaded. Take a look at the load method documentation for more information about how to use it.
Edit: Other examples to get the value to be manipulated
Using $.get() function:
$(function(){
$.get( "pathToYourFile", function( data ) {
var resourceContent = data; // can be a global variable too...
// process the content...
});
});
Using $.ajax() function:
$(function(){
$.ajax({
url: "pathToYourFile",
async: false, // asynchronous request? (synchronous requests are discouraged...)
cache: false, // with this, you can force the browser to not make cache of the retrieved data
dataType: "text", // jQuery will infer this, but you can set explicitly
success: function( data, textStatus, jqXHR ) {
var resourceContent = data; // can be a global variable too...
// process the content...
}
});
});
It is important to note that:
$(function(){
// code...
});
Is the same as:
$(document).ready(function(){
// code
});
And normally you need to use this syntax, since you would want that the DOM is ready to execute your JavaScript code.
Here's your issue:
You've got a script tag in the body, which is asking for the AJAX data.
Even if you were asking it to write the data to your shell, and not just spout it...
...that's your #1 issue.
Here's why:
AJAX is asynchronous.
Okay, we know that already, but what does that mean?
Well, it means that it's going to go to the server and ask for the file.
The server is going to go looking, and send it back. Then your computer is going to download the contents. When the contents are 100% downloaded, they'll be available to use.
...thing is...
Your program isn't waiting for that to happen.
It's telling the server to take its time, and in the meantime it's going to keep doing what it's doing, and it's not going to think about the contents again, until it gets a call from the server.
Well, browsers are really freakin' fast when it comes to rendering HTML.
Servers are really freakin' fast at serving static (plain-text/img/css/js) files, too.
So now you're in a race.
Which will happen first?
Will the server call back with the text, or will the browser hit the script tag that asks for the file contents?
Whichever one wins on that refresh is the one that will happen.
So how do you get around that?
Callbacks.
Callbacks are a different way of thinking.
In JavaScript, you perform a callback by giving the AJAX call a function to use, when the download is complete.
It'd be like calling somebody from a work-line, and saying: dial THIS extension to reach me, when you have an answer for me.
In jQuery, you'll use a parameter called "success" in the AJAX call.
Make success : function (data) { doSomething(data); } a part of that object that you're passing into the AJAX call.
When the file downloads, as soon as it downloads, jQuery will pass the results into the success function you gave it, which will do whatever it's made to do, or call whatever functions it was made to call.
Give it a try. It sure beats racing to see which downloads first.
I recommend not to use url: "./seeds/Ag.txt",, to target a file directly. Instead, use a server side script llike PHP to open the file and return the data, either in plane format or in JSON format.
You may find a tutorial to open files here: http://www.tizag.com/phpT/fileread.php
I'm working on a chat and I'm trying to figure out how I can detect that the user has left the page or not. Almost everything is being handled by the database to avoid the front end from messing up.
So what I'm trying to do is once the page is left for any reason (window closed, going to another page, clicking a link, etc.) an ajax call will be fired before a person leaves so I can update the database.
This is what I've tried:
$(window).unload(function(){
$.post("script.php",{key_leave:"289583002"});
});
For some odd reason, it wouldn't work, and I've checked the php code, and it works fine. Any suggestions?
Try this:
$(window).unload(function(){
$.ajax({
type: 'POST',
url: 'script.php',
async:false,
data: {key_leave:"289583002"}
});
});
Note the async:false, that way the browser waits for the request to finish.
Using $.post is asynchronous, so the request may not be quick enough before the browser stops executing the script.
This isn't the correct way of doing this... Suppose the OS just hangs or something happens in the browsers process then this event wont be fired. And you will never ever know when the user has left, showing him/her online ever after he/she has disconnected. Instead of this, what you can do is.
Try connecting a socket so that you can know the user is disconnected when the socket is disconnected
You can send a request to the server (say after every 1 sec) so that you can know that the user is still connected. If you didn't receive the request - even after 2 secconds - disconnect the user.
Try to add popup (prompt("leaving so early?")) after $.post. It may work. Tho it may be bad user experience. :)
This is related to the answer above. https://stackoverflow.com/a/10272651/1306144
This will execute the ajax call every 1 sec. (1000)
function callEveryOneSec() {
$jx.ajax({}); // your ajax call
}
setInterval(callEveryOneSec, 1000);
The unload event is not recommended to detect users leaving the page. From MDN:
Developers should avoid using the unload event ... Especially on mobile, the unload event is not reliably fired.
Instead, use the visibilitychange event on document and/or the pagehide event on window (see links for details). For example:
document.addEventListener('visibilitychange', function() {
if (document.visibilityState === 'hidden') {
$.ajax({
type: 'POST',
url: 'script.php',
async:false,
data: {key_leave: "289583002"}
});
}
});
Better yet, use Navigator.sendBeacon, which is specifically designed for the purpose of sending a small amount of analytics data to a server:
document.addEventListener('visibilitychange', function() {
if (document.visibilityState === 'hidden') {
navigator.sendBeacon('script.php', {key_leave: "289583002"});
}
});
I'm trying to perform a post query when the user leaves the page. The code I'm working with is
<script type="text/javascript">
window.onbeforeunload = function(){
var used = $('#identifier').val();
$.post('conversation.php?leave=true',{ud:used});
}
</script>
Is there anything wrong with what I'm doing here? The result I get in the FF error console is just saying that other non-related functions/variables are not defined (since they are unloading). Any tips or pointers for what I need to fix?
The simple answer is you can't make an asynchronous AJAX call in the beforeunload event reliably, it'll very likely be terminated before it finished, as the browser garbage collects the page. You can make a synchronous call, like this:
$.ajax({
type: "POST",
url: 'conversation.php?leave=true',
data:{ud:used},
async: false
});
Please don't do this though, as it traps your user in the page for longer than needed and prevents them from leaving, resulting in a negative experience. Note that this also locks up the browser while it executes, async: false should be avoided in every case possible.
I'm just starting to wean myself from ASP.NET UpdatePanels. I'm using jQuery and jTemplates to bind the results of a web service to a grid, and everything works fine.
Here's the thing: I'm trying to show a spinner GIF while the table is being refreshed (à la UpdateProgress in ASP.NET) I've got it all working, except that the spinner is frozen. To see what's going on, I've tried moving the spinner out from the update progress div and out on the page where I can see it the whole time. It spins and spins until the refresh starts, and stays frozen until the refresh is done, and then starts spinning again. Not really what you want from a 'please wait' spinner!
This is in IE7 - haven't had a chance to test in other browsers yet. Any thoughts? Is the ajax call or the client-side databinding so resource-intensive that the browser is unable to tend to its animated GIFs?
Update
Here's the code that refreshes the grid. Not sure if this is synchronous or asynchronous.
updateConcessions = function(e) {
$.ajax({
type: "POST",
url: "Concessions.aspx/GetConcessions",
data: "{'Countries':'ga'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
applyTemplate(msg);
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
}
});
}
applyTemplate = function(msg) {
$('div#TemplateTarget').setTemplate($('div#TemplateSource').html());
$('div#TemplateTarget').processTemplate(msg);
}
Update 2
I just checked the jQuery documentation and the $.ajax() method is asynchronous by default. Just for kicks I added this
$.ajax({
async: true,
...
and it didn't make any difference.
It's not the Ajax call that's freezing the browser. It's the success handler (applyTemplate). Inserting HTML into a document like that can freeze IE, depending on how much HTML there is. It's because the IE UI is single threaded; if you notice, the actual IE menus are frozen too while this is happening.
As a test, try:
applyTemplate = function(msg) {
return;
}
I don't remember precisely what caused it, but we had a similar issue with IE6 in a busy box and we fixed it with this incredible hack in the Javascript:
setTimeout("document.images['BusyImage'].src=document.images['BusyImage'].src",10);
That just sets the image source to what it was before, but it is apparently enough to jostle IE out of its stupor.
edit: I think I remember what was causing this: We were loading the animation into a div with display: none. IE loads it and doesn't start the animation, because it's hidden. Unfortunately it doesn't start the animation when you set the containing block to display: block, so we used the above line of code to trick IE into reloading the image.
The image freezes because while it is hidden the animation is disabled by IE.
To fix this, append the loading image instead of unhiding it:
function showLoader(callback){
$('#wherever').append(
'<img class="waiting" src="/path/to/gif.gif" />'
);
callback();
}
function finishForm(){
var passed = formValidate(document.forms.clientSupportReq);
if(passed)
{
$('input#subm')
.val('Uploading...')
.attr('disabled','disabled');
$('input#res').hide();
}
return passed;
}
$(function(){
// on submit
$('form#formid').submit(function(){
var l = showLoader( function(){
finishForm()
});
if(!l){
$('.waiting').remove();
}
return l;
});
});
Are you sure that its during the AJAX call that the GIF isn't spinning?
In your concessions.aspx place this line somewhere in the handling of GetConcessions:-
System.Threading.Thread.Sleep(5000);
I suspect that the gif spins for 5 seconds then freezes whilst IE renders and paints the result.
I know the question was regarding asynchronous ajax calls. However I wanted to add that I have found the following in my tests regarding synchronous ajax calls:
For Synchronous ajax calls. While the call is in progress (i.e. waiting for the server to respond). For the test i put a delay in the server response on the server.
Firefox 17.0.1 - animated gif continues to animate properly.
Chrome v23 - animated gif stops animation while the request is in progress.
well, this is for many reasons. First at all, when the ajax call back of the server, you will sense a few miliseconds your gif frozen, but not many relevant. After you will start to process information, and depending of the objects that you manipulate and how you do it, you will have more o less time your gif frozen. This is because the thread is busy processing information. Example if you have 1000 objects and your do a order, and move information, and also you use jquery and append, insert, $.each commands, you will senses a gif frozen. Sometimes it's imposible avoid all the frozen gifs, but yu can limit the time to a few miliseconds doing this: Make a list of response ajax, and process it each 2 seconds (with this you will have the results in a alone array and you wil call it with one setInterval and you avoid the bottle neck of try process one response when the before response is still processing). if you use JQuery don't use $.each, use for. Don't use dom manipulation (append,insert,etc..), use html(). In resume do less code, refactor, and procdess all the response (if you did more of 1) like only 1. Sorry for my english.
I had a similar problem with the browser freezing. If you are developing and testing locally, for some reason it freezes the web browser. After uploading my code to a web server it started to work. I hope this helps, because it took me hours to figure it out for myself.
I have seen this behavior in the past when making AJAX calls. I believe this is related to the fact that browsers are only single threaded, so when the AJAX call is returned the thread is working on the call, so consequentially the animated GIF needs to stop momentarily.
dennismonsewicz's answer is greate. Use spin.js and the site http://fgnass.github.com/spin.js/ shows the step which is quite easy.
Under heavy process we should use CSS animations.
No JS driven animations and GIFs should be used becacuse of the single thread limit otherwise the animation will freeze. CSS animations are separated from the UI thread.
Are you doing a synchronous call or asynchronous call? synchronous calls do cause the browser to seemingly lock up for the duration of the call. The other possibility is that the system is very busy doing whatever work it is doing.
Wrapping ajax call in setTimeout function helped me to prevent freezing of gif-animation:
setTimeout(function() {
$.get('/some_link', function (response) {
// some actions
});
}, 0);
Browsers are single-threaded and multi-threaded.
For any browser :
When you a called a function that contains a nested ajax function
java/servlet/jsp/Controller >
keep Thread.sleep(5000); in servlet to understand the async in ajax when
true or false.
function ajaxFn(){
$('#status').html('WAIT... <img id="theImg" src="page-loader.gif" alt="preload" width="30" height="30"/>');
$('#status').css("color","red");
$.ajax({
url:"MyServlet",
method: "POST",
data: { name: $("textarea").val(),
id : $("input[type=text]").val() },
//async: false,
success:function(response){
//alert(response); //response is "welcome to.."
$("#status").text(response);
$('#status').css("color","green");
},
complete:function(x,y){
//alert(y)
},
error:function(){
$("#status").text("?");
}
});
}