Updated on May 19, 2015
Call a previous AJAX request again
For a project I was trying to solve the issue of session timeouts while not frustrating the user after an ajax call. So the previous ajax call had to be saved and executed again after a successful log-in.
For example you have some management system that is open for a long time, but for safety sessions are not kept alive too long. However people might find themselves in the situation that they were still working on something while their session expired. So it would be nice for a user to execute an action, be prompted with a log-in form, and if it succeeds the original ajax call will automatically be made.
I used the CodeIgniter platform which has some nice functions to set the headers as well as jQuery for easy ajax handling. In the solution I propose it would be best to have proper handling of request headers. As W3C specs define the 401 Unauthorized is returned in case:
- the request requires user authentication.
- If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials.*
* i.e. the credentials were wrong or the the person is just not authorized
So to achieve this you first want to keep track of previous ajax calls. First of all we will extend the jQuery ajax object with an extra array called mostRecentCalls
.
1 2 3 | $(document).ready(function(){ $.ajax.mostRecentCalls = []; }) |
Then we keep track of each completed ajax call using $.ajaxComplete();
Because you might have several different ajax call throughout your website that should not interfere (for example timed polling of messages or notifications, some user statistics polling, etc.) it would be best to define namespaces for each type of ajax request that you want to keep the most recent from.
1 2 3 4 5 6 7 8 9 | $(document).ajaxComplete( function(ev, jqXHR, settings){ if(!(settings.namespace === false || typeof settings.namespace === 'undefined')){ // create new namespace if it does not exist yet. if(!$.isArray($.ajax.mostRecentCalls[settings.namespace])){ $.ajax.mostRecentCalls[settings.namespace] = []; } $.ajax.mostRecentCalls[settings.namespace] = settings; } }); |
In our ajax call we can then access the previous ajax call. Generall your current ajax call probably looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 | $.ajax({ url: 'my/request/url', data: myDataObj, success: function(data){ // data will be object with your content, // set it as content to your object $(target).html(data.myHtml); }, error: function(response){ alert('an error occured') } }) |
Yes, it’s not very neat error handling, but its just an example. You might also have defined deferred object methods like .done()
and .fail()
, however to make this work neatly you must extend the ajax object with at least the success callback as above. This way we can just have the previous saved settings used for the $.ajax object and all is set.
So how would that look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | $.ajax({ url: '', namespace: 'SPECIFIC_AJAX_CALL_ID', // success callback must be in the $.ajax object success: function(data){ // successful request, do whatever you want :) $(target).html(data.myHtml); }, // error callback may be in the $.ajax object, but can also be set as deferred .fail() method // error function shows the log-in form in case of 401 response error: function(response){ if(response.status == 401){ // move login form to your target // (assumed you already have a login form somewhere ;)) $(target).html($('#login-form')); // handle the log-in form $('#form-login', $(target)).on('submit', function(e){ // submit the form by ajax $.ajax({ url: $('#form-login').attr('action'), type: $('#form-login').attr('method'), data: $( '#form-login' ).serialize() }) .done(function(response){ // execute previous ajax call $.ajax( $.ajax.mostRecentCalls['SPECIFIC_AJAX_CALL_ID'] ); }) .fail(function(response){ // show the log-in form once more, now with an error $('h2', '#form-login').after('Your credentials were wrong.') $('#form-login').get(0).reset(); }) e.preventDefault(); return false; }) } } }) |
Good luck!