EXT JS - I would like to know how to check the json response for a session time out like if a user is idle for say 20 minutes or so if his session is expired or not
There is no standard way of handling session timeouts in ExtJS. ExtJS is a client-side library, used to create the user interface/front-end layer of an application, while session management takes place on the server side.
ExtJS Ajax requests implement a callback mechanism. It means that a certain Javascript function is assigned as the callback function, which is called when the Ajax request has finished (either successfully or unsuccessfully). Here's an example taken from ExtJS API Documentation - see parameters success and failure that define the callback functions:
// Basic request
Ext.Ajax.request({
url: 'foo.php',
success: someFn,
failure: otherFn,
headers: {
'my-header': 'foo'
},
params: { foo: 'bar' }
});
So, in the case of session timeout, you could (for example) construct a JSON response, which would contain some error code (defined by you), and an error message to be shown to the user. The callback function should then check if this error is returned from the server, and take necessary actions (show error message, redirect to login page, etc.) when that happens.
Note that in the above case, from ExtJS viewpoint, the Ajax request would actually be successful. When the HTTP request fails altogether (HTTP errors like 403 and such), the Ajax request is considered unsuccessful. This is important because it is usually possible to define different callback functions for successful and unsuccessful requests (as in the above sample code).
You can mock the timeout session...
var keepaliveHandler = new Ext.util.DelayedTask(function(){
Ext.Ajax.request({
url : '/keepalive',
method : 'GET',
success: function(response, options){
//dummy server call each 60 seconds
keepaliveHandler.delay(60000);
}
});
});
var timeoutHandler = new Ext.util.DelayedTask(function(){
//invalidate session
Ext.Ajax.request({
url : '/logout',
method : 'GET',
success: function(response, options){
Ext.MessageBox.show({
title: MessagesMap.getMessage('session.closed'),
msg: MessagesMap.getMessage('session.closed.message'),
buttons: Ext.MessageBox.OK,
fn: function() {
window.location.pathname = '/';
},
icon: Ext.MessageBox.WARNING
});
}
});
});
if(Ext.ux.SystemProperties.isLogged) {
keepaliveHandler.delay(60000);
timeoutHandler.delay(Ext.ux.SystemProperties.timeout);
//check for mouse movements
document.body.onmousemove = function(e) {
timeoutHandler.delay(Ext.ux.SystemProperties.timeout);
};
}
Related
I have beforeunload event in js which will hit the .asmx service method as provided below.
.js event
$(window).on("beforeunload", function () {
var d, str;
str = '{Id:"' + $('#hdnId').val() + '"}';
d = str;
$.ajax({
type: "POST", //GET or POST or PUT or DELETE verb
url: "../POC.asmx/fUpdateTimeInterval",
data: d,
contentType: "application/json; charset=utf-8",
dataType: "json", //Expected data format from server
async: true,
beforeSend: function () {
// BlockUI();
},
success: function (data, Type, xhr) {//On Successfull service call
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(errorThrown);
},
complete: function () {
},
failure: function () {
}
});
});
.asmx (Web Service)
[WebMethod(true)]
public int fUpdateTimeInterval(String Id)
{
return new MY_POC.DLL.Survey().fUpdateTimeInterval(Id);
}
The above service will then call the below mentioned method defined in DLL class file.
public int fUpdateTimeInterval(Int32 Id)
{
List<SqlParameter> objParam = new List<SqlParameter>()
{
new SqlParameter{ParameterName ="#Id",Direction=ParameterDirection.Input,DbType=DbType.Int32,Value= Id},
};
MY_POC.DLL.SqlHelper.ExecuteNonQuery("MY_UpdateTimeInterval", System.Data.CommandType.StoredProcedure, objParam.ToArray());
return 0;
}
Now problem is when the page gets load on browser for first time I am getting current auto ID of the inserted row. If I refreshes the browser, then beforeunload event gets fired and update the row of received ID only. But if I close the tab or browser then the compiler would hit the service method and stops after opening brace, it does not executing further & not even showing any error.
After execution stops, I am getting the following message at Output screen of vs, but not showing any error.
It sounds like execution of the request is being aborted because the browser is closing the connection.
You should consider using the Beacon API. It's well supported by almost all browsers and it's made for this purpose. From Mozilla's documentation:
The main use case for the Beacon API is to send analytics such as
client-side events or session data to the server. Historically,
websites have used XMLHttpRequest for this, but browsers do not
guarantee to send these asynchronous requests in some circumstances
(for example, if the page is about to be unloaded). To combat this,
websites have resorted to various techniques, such as making the
request synchronous, that have a bad effect on responsiveness. Because
beacon requests are both asynchronous and guaranteed to be sent, they
combine good performance characteristics and reliability.
You can also make your Ajax request synchronous to prevent the connection from closing but that will have an impact on your GUI as it will block until the request completes.
Question about store data population in isomorphic flux apps. (I'm using react, alt, iso and node but theory applies to other examples)
I have a flux 'store' (http://alt.js.org/docs/stores/) that needs to get data from an api:
getState() {
return {
data : makeHttpRequest(url)
}
}
and as the user navigates through the SPA, more data will be loaded via http requests.
I want this app to be isomorphic so that I can render the apps full html including latest data server side and return it to the user for fast initial page load.
react.renderToString() lets me render the app as html, and I can seed the data using alt&iso like:
storeData = { "MyStore" : {"key" : "value"}}; // set data for store
alt.bootstrap(JSON.stringify(storeData || {})); // seed store with data
var content = React.renderToString(React.createElement(myApp)); // render react app to html
The problem is that I will see errors when running the js server side as the store will want to make a http request which it wont be able to do (as xmlhttprequest wont exist in node)
Whats the best way to solve this problem?
The only solution I can think of would be to wrap the httprequest from the store with:
var ExecutionEnvironment = require('react/lib/ExecutionEnvironment');
...
if (ExecutionEnvironment.canUseDOM) {
// make http request
} else {
// do nothing
}
Any better ideas? Thanks in advance.
I would recommend hooking into your Ajax library or XMLHttpRequest directly if you are running serverside. Just shim it with code that supplies data directly from your database or application.
A quick example:
var noop= function(){}
window.XMLHttpRequest= function(){
console.log("xhr created", arguments);
return {
open: function(method, url){
console.log("xhr open", method, url);
// asynchronously respond
setTimeout(function(){
// pull this data from your database/application
this.responseText= JSON.stringify({
foo: "bar"
});
this.status= 200;
this.statusText= "Marvellous";
if(this.onload){
this.onload();
}
// other libs may implement onreadystatechange
}.bind(this), 1)
},
// receive data here
send: function(data){
console.log("xhr send", data);
},
close: noop,
abort: noop,
setRequestHeader: noop,
overrideMimeType: noop,
getAllResponseHeaders: noop,
getResponseHeader: noop,
};
}
$.ajax({
method: "GET",
url: "foo/bar",
dataType: "json",
success: function(data){
console.log("ajax complete", data);
},
error: function(){
console.log("something failed", arguments);
}
});
http://jsfiddle.net/qs8r8L4f/
I whipped this up in the last 5 minutes mostly using the XMLHTTPRequest mdn page
However if you are using anything not directly based on XMLHttpRequest or explicitly node aware (like superagent) you will probably need to shim the library function itself.
Other work to do on this snippet would be implementing errors and different content types.
I know that Firefox and jQuery don't allow sync requests with credentials. My problem is that I need to know if the user is logged in or not (by checking his session on the server by hitting an /echo endpoint).
Otherwise my Backbone application enters a bad state because when I navigate to a backbone route like #newActivity there is this logic in my controller:
if (Session.status!=Session.LOGGED_IN) {
Backbone.history.navigate('login', true);
return;
}
Session is a singleton object. In there if I hit async the /echo endpoint, until the time success is called my controller already thinks that we are not logged in.
Outcome: when the user refreshed the page he is always redirected in the login prompt.
If I make the request sync everything works ok with Chrome.
The request is:
$.ajax({
url: Config.serverUrl + "/rest/auth/echo",
type: 'GET',
dataType: "json",
async:false,
xhrFields: {
withCredentials: true
},
/* beforeSend: function(xhr) {
xhr.withCredentials = true;
},*/
crossDomain: true,
success: function (data) {
self.bootstrap(data)
self.globalCh.vent.trigger('loggedIn',data.username);
}
});
I kind of understand why they want to phase out sync queries, but sometimes they are necessary for not having an unstable application state.
Any workarounds or ideas about a better implementation?
you need to use promises and/or deferred objects.
http://api.jquery.com/category/deferred-object/
jQuery's AJAX call returns a promise. That means you can fire a callback whereever you want to when the ajax call is finished.
add a return to your ajax request.
function getLoginInformation() {
return $.ajax({
// your ajax call to check if the user is logged in or not
});
}
and then on page load, you fire the stuff that needs the login information AFTER you have it. Like this:
getLoginInformation().then(function(data) {
// load the app and everything else that needs credentials
});
I am sending lots of data using jquery ajax method to web sever and client side respond only after receiving acknowledgment from server, now suppose network connection lost in MIDDLE of ajax call then how to detect this situation.
$.ajax({
url:'server.php',
data:'lots of data from 200KB to 5MB',
type:'post',
success: function(data)
{
alert('Success');
//some stuff on success
},
error: function(XMLHttpRequest, textStatus, errorThrown)
{
alert('Failure');
//some stuff on failure
}
});
This is my code and and it does not give error in middle of ajax call if get internet is disconnected.
NOTE : I cant use time out because data size is vary from 200kb to 5MB and server response time calculation is not feasible.
Try this:
First create a "ping" ajax call with setInterval every 5 seconds
function server_ping()
{
$.ajax({
url:"url to ping",
type: "POST"
});
}
var validateSession = setInterval(server_ping, 5000);
then arm your .ajaxError trap:
$(document).ajaxError(function( event, request, settings ) {
//When XHR Status code is 0 there is no connection with the server
if (request.status == 0){
alert("Communication with the server is lost!");
}
});
Remember Ajax calls are Asynchronous by default, so when the pings are going to the server and the request cannot reach the server the value on the XHR status is 0, and the .ajaxError will fire and you must catch the error and handle the way you want it.
Then you can send your data to the server, if the connection is lost when sending the data you get the error reported by the ping.
If your server was not very crowded, probably you could use a timer to start detecting the connection regularly when you start transferring the data (by using another ajax calling, for instance each 5 seconds). now you can use timeout.
Btw,
1)timeout doesn't always means network error. sometimes server's down also causes "timeout"
2)if the driver is down on client device, xhr.status = 0, and no timeout
I had a similar problem and solved it with a simpel try/catch and a re-try delay of (say) 2 seconds:
function myAjaxMethod()
{
try
{
$.ajax({ ... });
} catch (err)
{
console.log(err.message);
setTimeout(function(){myAjaxMethod(),2000});
}
}
I faced a similar situation like yours and fixed it by having a network check for every 5 seconds and if network is disconnected i would abort the ajax request manually which will end the ajax request.
Here i get the ajax XmlHttpRequest in the beforeSend event of the Jquery ajax call and use that object to abort the ajax request in case of network failure.
var interval = null;
var xhr = null;
$.ajax({
beforeSend: function(jqXHR, settings) {
xhr = jqXHR; // To get the ajax XmlHttpRequest
},
url:'server.php',
data:'lots of data from 200KB to 5MB',
type:'post',
success: function(data)
{
alert('Success');
//some stuff on success
},
error: function(XMLHttpRequest, textStatus, errorThrown)
{
alert('Failure');
//some stuff on failure
},
complete: function(data)
{
alert('Complete');
//To clear the interval on Complete
clearInterval(interval);
},
});
interval = setInterval(function() {
var isOnLine = navigator.onLine;
if (isOnLine) {
// online
} else {
xhr.abort();
}
}, 5000);
Try adding timeout: while constructing your $.ajax({}).
Also make sure to set cache: false, helpful sometimes.
Refer to Jquery's ajax() : http://api.jquery.com/jQuery.ajax/#toptions
You will get much more information there!
My thought s on your problem[updated]
#RiteshChandora , I understand your concern here. How ever I can suggest you to do 2 things.
As you have post data ranging from 200kb to 5mb, you might want to choose a maximum timeout. and trigger for the same. Yes, this might be problematic, but with the design you chosen, the only way to monitor the POST progress is to do this way. if not, see point 2.
I went through the flow, you are asking the user to copy the response Json from FB to your url. there are some problems here,
The json data has sensitive information about the user, and he is posting it on a url without SSL encryption.
Why should you prompt the user to post the acquired data on to your server? it should be easier if you user sever side scripts. Also you should never post huge data from the client to the server in occasions like these, where you could retrieve the same form the FBserver->your sevrer on the server side.
My suggested solution : after the user is authenticated , retrieve his friends list on the server side. do whatever you want on the server side, and display the result on the users screen.
This way all the burden will be taken by your server, also there is no need for the user to do any nasty json posting on your url.
Btw, your app idea is cool.
error: function(xhr, textStatus, thrownError)
{
alert(xhr.status);
alert(thrownError);
alert(textStatus);
}
Try them..
TextStatus (besides null) are "timeout", "error", "abort", and "parsererror".
When an HTTP error occurs, thrownError receives the textual portion of the HTTP status, such as "Not Found" or "Internal Server Error."
If Internet disconnects,the response wont be received and maximum it would be a timeout message..
I have multiple ajax requests some request data every minute others are initiated by the user through a ui.
$.get('/myurl', data).done(function( data ){
// do stuff..
});
The request might fail due to an authentication failure.
I've setup a global .ajaxError() method for catching any failed requests.
$(document).ajaxError(function( e, jqxhr ){
// Correct error..
});
After I catch the error I reset authorization.
Resetting the authorization works but the user has to manually re initiate the ajax call (through the ui).
How do I resend the failed request using the jqxhr originally sent?
(I'm using jQuery for the ajax)
Found this post that suggests a good solution to this problem.
The main thing is to use $.ajaxPrefilter and replace your error handler with a custom one that checks for retries and performs a retry by using the closure's 'originalOptions'.
I'm posting the code just in case it will be offline in the future. Again, the credit belongs to the original author.
// register AJAX prefilter : options, original options
$.ajaxPrefilter(function( options, originalOptions, jqXHR ) {
originalOptions._error = originalOptions.error;
// overwrite error handler for current request
options.error = function( _jqXHR, _textStatus, _errorThrown ){
if (... it should not retry ...){
if( originalOptions._error ) originalOptions._error( _jqXHR, _textStatus, _errorThrown );
return;
};
// else... Call AJAX again with original options
$.ajax( originalOptions);
};
});
In this case, I would write a specific handler for the 403 status code, which means unauthorized (my server would return a 403 too). From the jquery ajax docs, you can do
$.ajax({
statusCode: {
403: function() {
relogin(onSuccess);
}
}
});
to achieve that.
In that handler, I would call a relogin method, passing a function that captures what to do when login succeeds. In this case, you could pass in the method that contains the call you want to run again.
In the code above, relogin should call the login code, and onSuccess should be a function that wraps the code you execute every minute.
EDIT- based on your clarification in comment, that this scenario happens for multiple requests, I personally would create an API for your app that captures the interactions with the server.
app = {};
app.api = {};
// now define all your requests AND request callbacks, that way you can reuse them
app.api.makeRequest1 = function(..){..} // make request 1
app.api._request1Success = function(...){...}// success handler for request 1
app.api._request1Fail = function(...){...}// general fail handler for request 1
/**
A method that will construct a function that is intended to be executed
on auth failure.
#param attempted The method you were trying to execute
#param args The args you want to pass to the method on retry
#return function A function that will retry the attempted method
**/
app.api.generalAuthFail = function(attempted, args){
return function(paramsForFail){ // whatever jquery returns on fail should be the args
if (attempted) attempted(args);
}
}
so with that structure, in your request1 method you would do something like
$().ajax({
....
statusCode: {
403: app.api.generalAuthFail(app.api.request1, someArgs);
}
}}
the generalAuthFailure will return a callback that executes the method you pass in.
The code below will keep the original request and it will try to success 3 times.
var tries = 0;
$( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
if(tries < 3){
tries++;
$.ajax(this).done(function(){tries=0;});
}
});
You could possibly go by the option of naming each one of your functions and then recalling them as stated in hvgotcodes' answers.
Or
You can use a reusable function to setup a request while extending the defaults:
function getRequest( options ){
var // always get json
defaults = { dataType: 'json' },
settings = $.extend( defaults, options );
return // send initial ajax, if it's all good return the jqxhr object
$.ajax( settings )
// on error
.fail(function( jqxhr, e ){
// if the users autherization has failed out server responds with a 401
if( jqxhr.status === 401 ){
// Authenticate user again
resetAuthentication()
.done(function(){
// resend original ajax also triggering initial callback
$.ajax( settings );
});
}
});
};
To use the above function you would write something like this:
getRequest({
url: 'http://www.example.com/auth.php',
data: {user: 'Mike', pass: '12345'},
success: function(){ // do stuff }
});
The getRequest() could probably be made recursive and/or converted into a jQuery plugin but this was sufficient for my needs.
Note: If the resetAutentication function might faile, getRequest() would have to be recursive.