Isomorphic JS - httpRequest client side only - javascript

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.

Related

Asp.Net Service method Is Not Executing or Calling Inner Method or Statement on BeforeUnload event

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.

React jQuery AJAX global caching

I am developing React application and for frontend AJAX requests I use jQuery, but I want to cache my requests like angular http.get(url, {cache: true }) does.
Is there any way which can help me do this global caching for GET requests.
I tried to add cache: true property to request but it seems not working.
For example my code looks like this
$.ajax(source, {
method: 'GET',
data: {
c: count,
p: period
},
cache: true,
success: (response) => {
}
})
I have tried also
$.ajaxSetup({
cache:true
});
for all requests, but unfortunatley I can see request under Chrome devtools network tab, as well as in my server logs.
So I want to prevent from doing same request if data and url is same.
I can create some storage myself, but I think there should be default way for doing this.
Thanks in advance!
One approach could be checking if the last request data are the same than the current.
var lastRequestedData = {};
function myAjaxRequest(requestData) {
if (JSON.stringify(requestData) != JSON.stringify(lastRequestedData)) {
lastRequestedData = requestData;
alert('Makes the ajax request: '+ JSON.stringify(requestData));
//$.ajax(...)
}
}
myAjaxRequest({"c":1,"p":2}); // Fire
myAjaxRequest({"c":1,"p":2}); // Not fire
myAjaxRequest({"c":2,"p":3}); // Fire

Nodejs Facade pattern for interact with different API web services

I am working with a NodeJs App and I have to call to a online web service in the logic part.
The problem is that if that web service is taken down, the whole system stop working.
To deal with this I have though in use a Facade pattern, adding another web service with the same functionality, and one offline file with similar information (but not as good as the web service's).
The idea is call the Facade (javaScript file?) from the logic part. It has to choose first the primary web service and call it, if it is down, go for the second one, and if it is also down, call the offline data file.
Any idea about how to stucture this on NodeJS?
This is a possible solution
// Simple GET request example:
$http({
method: 'GET',
url: '/someUrl1'
}).then(function (response) {
// this callback will be called asynchronously
// when the response is available
}, function (response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
// In case it fails
$http({
method: 'GET',
url: '/someUrl2'
}).then(function (response) {
// this callback will be called asynchronously
// when the response is available
}, function (response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
// If it fails again, use JSON file here
});
});

How to use HTTP.call with beforeSend on the client?

Meteor's recent update added an option to the http package to use beforeSend, allowing us to access the xhr object on the client. I am on occasion uploading or downloading large files on the client and I want to have a progress indicator as well as a cancel option. I can not get beforeSend to work, unfortunately.
Question
What is the proper way to use beforeSend and/or why does my code not work?
What Happens
Http.call runs completely, but my beforeSend function is never executed.
Relevant Packages
Meteor 1.2.1
http 1.1.1
aldeed:http
Relevant Client Code
httpProgress = function(xhr) {
console.log('I never see this');
xhr.onprogress = function(e) {
if (e.lengthComputable) {
setProgress((e.loaded / e.total) * 100, 'downloading...', true);
}
else{
setProgress(-1, 'downloading...', true);
}
};
};
HTTP.call('GET',url, {
beforeSend: httpProgress,
headers: {
'Accept': '*/*'
},
responseType: 'arraybuffer' //using aldeed:http here
}, function(error, result) {
...
}
);
Meteor's Documentation on beforeSend
On the client, this will be called before the request is sent to allow
for more direct manipulation of the underlying XMLHttpRequest object,
which will be passed as the first argument. If the callback returns
false, the request will be not be send.
HTTP.call method in aldeed:http package does not support any beforeSend parameter yet. You can check it in source code here

EXT JS Session Timeout

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);
};
}

Categories