It seems there are some very good resources on my question - at least the basics. But there are still a few dark areas for myself.
First - What I am trying to do.
I am having users "wait" at an intermediary page while I check to see if they have submitted the correct information from another resource (ie. SMS or email) to confirm their subscription to my service. The page should asynchronously check ever couple of seconds to see if they have completed the required steps and their status has been set to '1' or 'active' in the database.
Completing the ajax request seems pretty straightforward - the timing however, I am a little thick about.
Also, what is it that I am trying to do with the information I am retrieving - great, so the user has been set to 'active' and I can retrieve that value - but then what do I use to redirect them to the final or 'thank you' page? Is it a javascript variable that should hold the value then redirect?
Sorry if this seems a little discombobulated, but this is my first try at Ajax & timed refreshes/responses.
I'd do a predefined number of intervals on the ajax call - after 3 attempts, fail with a message:
var attempts = 0;
var validation_attempt = setInterval(function(){
if(attempts > 3)
{
clearInterval(validation_attempt);
$('#my_div').html('No activity, try again later');
return false;
}
$.ajax({
url: '/my_file.php',
/* other params */
success:function(data){
if(data == 'ok')
{
clearInterval(validation_attempt);
$('#my_div').html('Your account has been approved');
}
else
{
attempts++;
}
}
});
},3000); // 3 seconds
This should essentially let the user wait for 9 seconds at the most before seeing a "No activity, try again later" message.
Your "waiting" page can poll with ajax for completion. It might poll every 15-20 seconds initially, back up to once a minute after a little while and then stop polling all together after awhile. In all cases, make sure you don't keep polling forever as this will be bad for your backend if the user never completes their end of the subscription process.
If the ajax polling gets a successful answer, I would think you would then redirect the user to one of two places:
1) A page that just indicates "Success - you are now subscribed" and tells them what to do next.
or
2) The opening web page for actually using the service. This may be a login page or perhaps you can already log them in automatically so you take them to the open page for the service.
You can do this redirect either in client-side javascript (e.g. it already knows where to redirect the user in all scenarios) or you can include the redirection URL in that actual ajax response so the flow of pages can be controlled server-side. You can do it either way.
I was coding this in response to your question. I think I'll post it in case it is useful:
var active = false, i, t;
// check 'active' for truthyness, if so kill timers
function checkActive() {
if(active) {
clearInterval(i);
clearTimeout(t);
window.location.href = "success.html";
}
return false;
}
// recursively call URL to check 'active' status
function checkStatus() {
$.post("checkStatus.php", { some: "variable" }, function(resp) {
if(resp !== "1") {
t = setTimeout(checkStatus, 2000);
} else {
active = true;
}
});
}
$(document).ready(function() {
checkStatus();
i = setInterval(checkActive, 2000);
});
You can try using a server push (comet) rather than ajax for this solution.
Related
The apache server I am using to develop my system will not respond to request while the scripts that control the polling of messages is being run. This only happends on a domain level meaning that I can send an http request to any other apps hosted localy and get a response. When I do eventually get a response from this its about a minute later.
Here is the Js
window.fetch_messages = function ()
{
var last_message = $("div.message:last").attr('data-ai_id');
var last_message_status = $("p.message_status:last").text();
var project_id = getParameterByName('project-id');
$.ajax({
url:'/project_messages',
type:'POST',
data:{ project_id:project_id, latest_message:last_message, status:last_message_status },
timeout:50000,
async: true,
success:new_messages, // This upon completion also resends the request
error:function(data){ console.log(data); setTimeout(fetch_messages(),50000); }
});
}; // When On the page that uses this I call this function to start polling
Here is the server side code
do
{
// Check for status change
$status_change = $this->mentor_model->query_status($this->project_id, $this->last_message_id, $this->last_message_status, $_SESSION['user']);
// Check for new messages
$messages = $this->mentor_model->query_messages($this->project_id, $this->last_message_id);
// If there is a status update or new message.
if($messages || $status_change)
break;
usleep(1000000);
}
while(empty($messages) && empty($status_change));
echo json_encode(array("messages"=>$messages, "status"=>$status_change));
exit;
While this action is being run The server takes a long time to handle any request weather it be a GET, POST or another AJax request. Iv also tried changing both code sets to no avail as long as its long polling, the server will take a long time to handle.
Do I have this wrong or is there some apache setting I'm suppose to change. Using xamp on windows 8.1 also tried wamp with no change
Thanks to steven for this. Ansewer taken straight from the source of php manual page
for session_write_close();
You can have interesting fun debugging anything with sleep() in it if
you have a session still active. For example, a page that makes an
ajax request, where the ajax request polls a server-side event (and
may not return immediately).
If the ajax function doesn't do session_write_close(), then your outer
page will appear to hang, and opening other pages in new tabs will
also stall.
I'm creating online chat, but I'm wondering while using jQuery .load() in my script, my browser seems to get slow. When i checked the inspect element "Net" section, it loads bunches of GET-data... etc.
I would like to know if there's a better script solution with this code to prevent chat being heavy in the background while the data keeps looping in the background to check who's keep coming online/offline.
setInterval('loadThis()', 5000);
function loadThis () {
$("#loads").load('includes/users.php', function(){
$(".chat-side-panel li").each(function(i){
i = i+1;
$(this).addClass("stats"+i);
var status = $(".stats"+i).find("span.bullet").data("status"),
flag = $(".stats"+i).find("span.mail").data("flag");
if(status == 1) {
$(".stats"+i).find("span.bullet").addClass("online");
}
if(flag == 1) {
$(".stats"+i).find("span.mail").addClass("active");
}
});
});
}
the Chat-Side-Panel will be the main panel, and LI will be the listings of users including their status (online/offline) and flag (message received). As for the standard, what can you suggest for the setInterval time loading (if 5sec. is enough) or should i increase it.
Thanks for your input for this.
PS. We're doing this with both PHP/MySQL also.
One issue I see is that you keep re-querying the DOM for the same elements. Get them once, re-use them thereafter:
var load_target = $('#loads');
function loadThis () {
load_target.load('includes/users.php', function () {
load_target.find('.chat-side-panel li').each(function (i) {
var stats_li = $(this),
bullet = stats_li.find('span.bullet'),
mail = stats_li.find('span.mail');
bullet.toggleClass('online', (bullet.data('status') == 1))
mail.toggleClass('active', (mail.data('flag') == 1));
});
});
}
I don't know all of your involved logic or what the rest of your system looks like, so this particular code may not work exactly. It should simply serve as a re-factor done in a vacuum to show what that function could look like if you stopped hitting the DOM so hard.
Also, use of setInterval is not generally recommended. If the load of the remote file takes a while, you could end up calling loadThis() again before a previous one was completed. This would compound your DOM issues if calls to loadThis() began stacking up. Recursive use of setTimeout is preferred in a situation like this. Here is the above code modified to run recursively, and some usage examples below that:
var load_target = $('#loads'),
loadThis = function (start_cycle) {
$.ajax({
url: 'includes/users.php',
dataType: 'html',
type: 'GET',
success: function (response) {
load_target
.html(response)
.find('.chat-side-panel li').each(function (i) {
var stats_li = $(this),
bullet = stats_li.find('span.bullet'),
mail = stats_li.find('span.mail');
bullet.toggleClass('online', (bullet.data('status') == 1))
mail.toggleClass('active', (mail.data('flag') == 1));
});
},
complete: function () {
if (typeof start_cycle !== 'boolean' || start_cycle) {
load_target.data('cycle_timer', setTimeout(loadThis, 5000));
}
}
});
};
//to run once without cycling, call:
loadThis(false);
//to run and start cycling every 5 seconds
loadThis(true);
// OR, since start_cycle is assumed true
loadThis();
//to stop cycling, you would clear the stored timer
clearTimeout(load_target.data('cycle_timer'));
Last years (around 2012) I developed a chat system for a social network, and saw that
Using setInterval issue is when the request is being sent regularly, without waiting or carry about the result of the first requests in the queue. Sometimes the script can not respond and Mozilla or IE asks the user whether he should block or wait for the non-responding script.
I finally decided to use setTimeout instead. Here is what I did (I use $.getJSON so please study the example and how can use load instead)
function loadThis () {
$.getJSON('url').done(function(results){
//--use the results here
//then send another request
setTimeOut(function(){
loadThis();
},5000);
}).fail(function(err){
//console.log(print(err))
setTimeOut(function(){
loadThis();
},1000);
});
}
loadThis();
PS.: I would like to mention that the time depends on our many items are to be retrieved in your users.php file. Maybe you should use the paging tip. Your users.php can then treat url params users.php?page=1&count=100 for the first request, users.php?page=2&count=100 for the second until the results rows number is 0.
EDITS: In addition, I suggest you consider not interacting with the DOM every time. It is important too.
I have constructed a PHP file which scrapes a web page (using cURL) to obtain some data, and outputs it to the screen in JSON format.
The target website involves some redirects which temporarily outputs data to my PHP file. Once the redirects have completed successfully, the JSON is presented as expected. The problem that I am encountering is that when I try to access the JSON using jQuery's $.ajax() method, it sometimes returns the incorrect data, because it isn't waiting for the redirects to complete.
My question is if it's possible to tell the AJAX request to wait a certain number of seconds before returning the data, thus allowing time for the redirects in the PHP script to execute successfully?
Please note that there is no cleaner solution for the page scrape, the redirects are essential and have to be outputted to the screen for the scraping to complete.
There's always timeout in the settings.
jQuery docs:
timeout Number
Set a timeout (in milliseconds) for the request. This will
override any global timeout set with $.ajaxSetup().
The timeout period starts at the point the $.ajax call is made;
if several other requests are in progress and the browser
has no connections available, it is possible for a request
to time out before it can be sent. In jQuery 1.4.x and below,
the XMLHttpRequest object will be in an invalid state if
the request times out; accessing any object members may
throw an exception. In Firefox 3.0+ only, script and JSONP
requests cannot be cancelled by a timeout; the script will
run even if it arrives after the timeout period.
You should use promise() in jQuery.
You could always store the result of your ajax call and then wait for the redirects to finsih, i.e.:
$.ajax({
success: function(e)
{
var wait = setTimeout(function(){ doSomethingWithData(e.data); }, 5000); //5 sec
}
})
Alternatively, you could set up an Interval to check if something happened (redirect finished) every x amount of ms. I'm assuming your redirects are letting you know they completed?
http://examples.hmp.is.it/ajaxProgressUpdater/
$i=0;
while (true)
{
if (self::$driver->executeScript("return $.active == 0")) {
break;
}
if($i == 20) {
break;
}
$i++;`enter code here`
echo $i;
usleep(10000);
}
i have a dynamic search in php with jquery.
When i'm entering a letter, an ajax call starts.
My problem is, that all ajax calls are working till end, so that every letter is a full call.
When a user is entering a full word then i have unused requests.
How can i stop the unused calls?
Thank you very much
Use timeouts to delay the request for a few millisecond, and clear it when a new key is pressed.
something like
var searchtimeout;
$('#search').keyup( function(){
if (searchtimeout)
{
clearTimeout(searchtimeout);
}
searchtimeout = setTimeout(function(){
// initiate the ajax call here..
}, 300);
} );
Either use a button to process the request that the user has to click when their finished or perhaps use something like debouncing.
One way you could do it , is to send the request when the user presses the return key , or atleast wait a few seconds ( 1-3 ) to see if the user stoped typing then make the request , you don't have to do the search for all changes on the input box .
Why dont you use the autocomplete plugin in jquery.. I am assuming you have handcoded the dynamic lookup.. auto complete takes care of most of these things and it is also configurable as to after how many letters you want to post to the server..it also implements caching.
I have used it in a lot of asp.net projects and it is pretty neat..
docs.jquery.com/Plugins/autocomplete
Ok, here is my solution:
if (searchtimeout)
{
clearTimeout(searchtimeout);
}
searchtimeout = setTimeout(function(){
if(x){
x.abort();
alert("MACH WEG!");
}
x = $.post(url + "ajax.html?nsearch=1&ckey="+SID, {queryString: ""+inputString+""}, function(data) { // Do an AJAX call
$('#suggestions').fadeIn(); // Show the suggestions box
$('#suggestions').html(data); // Fill the suggestions box
x = null;
});
}, 300);
I'm sure you're all familiar with the voting systems that use AJAX (Um... look right over there <----)
I have something similar and when you vote up or down it uses AJAX to request the new value from votes.php. The problem is that I am using a session to get the userid so a person can only vote once. What happens if they sit on the page for an hour and then vote so the session is no longer there? What would be a good way of handling this situation? Should I redirect their page to the login screen? If so, how can I do that from the votes.php page that is being referenced by the AJAX request? Am I overlooking a good way of handling this situation? Any advice would be helpful.
Consider returning an http status of 401, and a JSON object detailing the reason. If you're using jQuery, that'll drop you to the error() callback, which you can then parse your object.
$.ajax({
data: {},
dataType: 'html',
success: function(data) {
// do whatever here
},
type: 'POST',
url: 'myserver.com',
error: function(XMLHttpRequest, textStatus, errorThrown) {
// XMLHttpRequest.responseText has your json string
// XMLHttpRequest.status has the 401 status code
if (XMLHttpRequest.status === 401) {
location.href = 'login.php';
}
}
});
I'm not familiar with PHP anymore, but this should work for just about any environment. You may have to suppress any automatic login form redirection though. In asp.net mvc the framework will see the 401 and push the default login form back, with a status of 200.
You should only store a link to the users identity in the session. Use sessions to identify a user as x and then get user x's information from the database.
If your problem is with users sessions timing out then you should reconsider how you're using your sessions. Perhaps make them last until the browser closes? If you really want to make them a duration, then perhaps ping the server in intervals to keep the session alive.
Decide in your php script whether or not the user should be able to vote. If the session isn't set, or if they have already voted, return a message that you can identify with on the client side. If they already voted perhaps return "voted":"true" in a JSON object. Use JS to parse this object and understand what it means, taking the appropriate action. If the session isn't set, perhaps return "session_set":"false", and then make javascript redirect with a window.location = "login.php" etc.
Only increment the counter for the user on a successful return of a counted vote.
This is an old thread, but I wanted to share my solution that is working really well.
In my framework the system redirects the user to the login form any time they try to access a page and the session has timed out or is not valid.
I added to the top of the login form the following html comment:
<!--LOGINFORM-->
I created a wrapper for jQuery's $.ajax function which checks for this string on every request, and if it is there it shows a dialog popup saying that their session has timed out.
You can use this by just calling:
ajax.get('http://someurl.com', function(data){
//Do stuff
});
Hope it helps someone.
var ajax = {
check_login : function(resp){
if (resp.substring(0, 16) === "<!--LOGINFORM-->"){
// Show a popup or redirect them to login page!
return true;
}
return false;
},
get : function(url, success){
if (typeof data =='undefined'){
data = null;
}
$.ajax({
url: url,
type : 'GET',
success : function(resp){
if (!ajax.check_login(resp)) {
success(resp);
}
},
});
}
};
You structure the Javascript code that makes the Ajax request to accept a special result (say, -1 where a >=0 number would normally be, such as, a count of votes) to mean "sorry bub, you're timed out" and redirect to the re-login page (which can take as an optional parameter a message explaining to the user they timed out, &c).
You could create a javascript function that could ping the server every 10 minutes via something like
setTimeout("Ping()", 60000);
If you want to navigate the user to the login page if they connect with a faulty session then I would first verify the session and if it fails send a
header("Location: ...");
http://ca2.php.net/manual/en/function.header.php
From a user perspective, the best solution is to pop up a message and login form, saying something like "You are not logged in or your session timed out". Digg does this very well.
As for the actual AJAX implementation, swilliams' 401 suggestion is solid. Alternatively, you can simply return a specific string on failure.