Ajax - Function to check if url exists before send request - javascript

I am writing a function to grab a json file from a website/server and save it in local storage with the code:
function donators() {
var jsonURL = "http://mywebsite.com/donators.json";
var xhr = new XMLHttpRequest();
xhr.open("GET", jsonURL, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
localDataStore.set("fb_donators", xhr.responseText);
}
};
xhr.send();
}
The above code works perfectly fine when the json file can be reached, but if my server goes down and the file cannot be reached my script halts at the line with xhr.send() with the error:
GET http://mywebsite.com/donators.json net::ERR_NAME_NOT_RESOLVED
Is there a way I can detect check if url can be reached before the send request to stop the send the request and allow the rest of my script to continue to run instead of getting halted at xhr.send()?
Thanks!

You can use a try block for this. It still requires the HTTP request, but it will fail gracefully and you can handle the error any way you'd like.
function donators() {
var jsonURL = "http://mywebsite.com/donators.json";
var xhr = new XMLHttpRequest();
xhr.open("GET", jsonURL, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
localDataStore.set("fb_donators", xhr.responseText);
}
};
xhr.timeout = 5000;
xhr.ontimeout = function() {
alert( 'The operation timed out.' );
}
try { xhr.send(); } catch( err ) {
alert( 'Error getting data: ' + err.message );
}
}

Related

How to get html source of page, after all it scripts was called?

I'am trying to parse site. The site (i suppose) using scripts and data bases to load data from (dynamically?). And this is my problem... I am trying to grab data through C# (unfortunately i don't have access to code right now) or JS. And it seems like either C# and JS, get only template of the site, but don't wait until all scripts executed. So this is my question, is there any way to get ALL html source? Maybe call scripts somehow. Or make a request, wait for 10 seconds, and then write source html data into variable?
Here is my JS code.
function request(link)
{
var xhr = new XMLHttpRequest();
xhr.open('GET', link, true);
xhr.onreadystatechange = function() .
{console.log(xhr.readyState);};
xhr.send();
let data = xhr.responseText;
var tempDiv = document.createElement('div');
tempDiv.innerHTML = data.replace(/<script(.|\s)*?\/script>/g,
'');
return tempDiv;
}
function loadFile(url, timeout, callback)
{
var args = Array.prototype.slice.call(arguments, 3);
var xhr = new XMLHttpRequest();
xhr.ontimeout = function () {
console.error("The request for " + url + " timed out.");
};
xhr.onload = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
callback.apply(xhr, args);
} else {
console.error(xhr.statusText);
}
}
};
xhr.open("GET", url, true);
xhr.timeout = timeout;
xhr.send(null);
let data = xhr.responseText;
return data;
}
function showMessage (message) {
console.log(message + this.responseText);
}
function include(scriptUrl)
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", scriptUrl);
xmlhttp.onreadystatechange = function()
{
if ((xmlhttp.status == 200) && (xmlhttp.readyState == 4))
{
eval(xmlhttp.responseText);
}
};
xmlhttp.send();
let data = JSON.parse(xmlhttp.responseText);
var tempDiv = document.createElement('div');
tempDiv.innerHTML = data.replace(/<script(.|\s)*?\/script>/g,
'');
return tempDiv;
}
All this functions do not work as i want.
This isn't really practical - you're trying to load an HTML page, all associated scripts, then run them on the HTML page as if they were in a proper browser environment, but within your current browser session.
This sort of thing is feasible with the jsdom library if you were running on the server-side (NodeJS), because it simulates browser behaviour: https://github.com/jsdom/jsdom. So you could do
JSDOM.fromURL("https://example.com/", { runScripts: "dangerously" }).then(dom => {
console.log(dom.serialize()); //turn the page back into HTML
});
...to get the whole thing.

Send javascript errors to servers

I have a script that capture the errors and send them to my server. But I'm worried that if I have a lot of users, and every user gets a couple errors, it may collapse my server.
This is my code:
window.onerror = function(msg, url, num) {
try {
var clientSideErrorInfo = {
message: msg,
url: url,
num: num
};
var xhr = new XMLHttpRequest();
xhr.open("POST", 'http://domain/api/v1/browser/', true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(clientSideErrorInfo));
console.log(clientSideErrorInfo)
} catch (e) {
console.log(e);
// Don't allow for infinitely recursively unhandled errors
return true;
}
};
Is there a way to send a group of logs instead of sending them one by one?
Thanks
Instead of sending the error at the moment you get it, you could collect all errors into a global variable and you send them using an interval. This way you can limit how many errors you want to send at a same time and you could increase your interval as well.
var errorSend = {};
errorSend.listErrors = [];
errorSend.maxErrors = 50;
errorSend.interval = 100;
window.onerror = function(msg, url, num) {
var clientSideErrorInfo = {
message: msg,
url: url,
num: num
};
listErrors.push(clientSideErrorInfo);
console.log(clientSideErrorInfo)
};
function sendErrors() {
if (errorSend.listErrors>errorSend.maxErrors) {
console.log("Too many errors to send");
return;
}
var errors = {list: errorSend.listErrors};
var xhr = new XMLHttpRequest();
xhr.open("POST", 'http://domain/api/v1/browser/', true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(errors));
}
setInterval(sendErrors,errorSend.interval);
Something very simple,umm:
var body =[];
setInterval(function(){
//Using a copy of the error queue
let batch = body.slice();
var xhr = new XMLHttpRequest();
xhr.open("POST", 'http://domain/api/v1/browser/', true);
xhr.setRequestHeader("Content-Type", "application/json");
let myJson = JSON.stringify(body);
xhr.send({
data:{
param: myJson
}
});
//Updating the main queue to contain only unsent error messages
body=body.slice(batch.length,body.length);
},time_you_specify);
window.onerror = function(msg, url, num) {
try {
var clientSideErrorInfo = {
message: msg,
url: url,
num: num
};
body.push(clientSideErrorInfo);
console.log(clientSideErrorInfo)
} catch (e) {
console.log(e);
// Don't allow for infinitely recursively unhandled errors
return true;
}
};
Is not problem for this job but if you have a lot of errors in you web app can be problem. First you will need to setup your javascript code to the perfect state. In that case you idea is good ( catch every possible error ) . Just put it in some table on server .
Heres from mozilla dev site about param :
window.onerror = function (msg, url, lineNo, columnNo, error) {
var string = msg.toLowerCase();
var substring = "script error";
if (string.indexOf(substring) > -1){
alert('Script Error: See Browser Console for Detail');
} else {
var message = [
'Message: ' + msg,
'URL: ' + url,
'Line: ' + lineNo,
'Column: ' + columnNo,
'Error object: ' + JSON.stringify(error)
].join(' - ');
alert(message);
}
return false;
};
Very important use (userAgent) detectBrowser data , you must know which device is used also which browser is used -just add data intro your function. In 90% your client error will happend only on specific platforms . For example on android chrome ver < 23 ...
Please don't use interval for this kind of tasks , just on error catch event send error log to the server just like you already did!
It is better to use message queueing infrastructure, if you are expecting millions of messages
some sample

clearInterval not working with XMLHttpRequest

I'm trying to get the result, next time of the game in database. I used XMLHttpRequest with 5s delay of setInterval to fetch data. If the status of the request is 200. The code works well. However, if the status is not 200. The clearInterval will not work but console.log still works.
var _resInterval;
_resInterval = setInterval(function() {
var xhr = new XMLHttpRequest();
xhr.open("POST", "/index.php/forms/getDDResult/" + id, true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onload = function() {
if (xhr.status === 200) {
var _resp = JSON.parse(xhr.responseText);
console.log(_resp);
if (parseInt(_resp.interval) >= 0) {
clearInterval(_resInterval);
restartGame(parseInt(_resp.interval));
}
} else {
console.log("error");
clearInterval(_resInterval);
}
};
xhr.send();
}, 5000);
UPDATE: recursive function
function getGameResult() {
var xhr = new XMLHttpRequest();
xhr.open("POST", "/index.php/forms/getDDResult/" + id, true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onload = function() {
if (xhr.status === 200) {
var _resp = JSON.parse(xhr.responseText);
console.log(_resp);
if (parseInt(_resp.interval) >= 0 && _resp.result != "Not available") {
restartGame(parseInt(_resp.interval));
} else {
setTimeout(function() {
getGameResult();
}, 5000);
}
}
};
xhr.send();
}
Am I doing it the right way or should I change it to recursive function? Thanks.
-- Lara
The problem is that there's a possibility where the clearInterval is called and an XHR is pending a response. When the browser receives the response, the timer is long gone, but still has to handle the response.
If you want your periodic XHR to wait for the response of the previous before launching another, the recursive setTimeout is a better option.

xmlHttpRequest status = 0

I have a website (wagtail CMS) running at AWS at domain:8000 and my API running at domain:8801
On my webpage I try to get some info from API by using JS (Access-Control-Allow-Origin header is set correctly at API, it's a django-based app)
Unfortunately the following code returns only xhr.status = 0 and empty responseText no matter what I try to access.
When I put domain:8000 at xhr.open('GET','http://domain:8000',true) everything works just fine, I see my html code.
function load() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://domain:8801/api/', true);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.send();
if (xhr.status != 200) {
alert( "ERR" ); --always ERR in browser
}
else {
alert( "SUCCESS" );
}
}
On the API side I see all my requests, status=200 in server console.
You're supposed to use a callback function to catch the response from a request using the XMLHttpRequest object. Do something like this instead:
xhr.addEventListener('readystatechange', function() {
if (xhr.status != 200) {
alert( "ERR" ); --always ERR in browser
} else {
alert( "SUCCESS" );
}
}
});
Look here for docs and an examples on doing that.
You need to wait for xhr.readyState == 4 before xhr.status is at all valid (actually I think it's valid at 3, but lets keep consistent with 99.999% of code in the wild)
function load() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://domain:8801/api/', true);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status != 200) {
alert( "ERR" ); --always ERR in browser
}
else {
alert( "SUCCESS" );
}
}
};
xhr.send();
}

how to load json from url using javascript?

I'm new to javascript which should be really simple to solve, but I am lost as of now.
I have a url: http:getall.json
Using JavaScript (not JQuery or php. Just JavaScript), I want to read this JSON string and parse it. That's it.
access to your url doesn't work, you should show the JSON result. In javascript to get JSON object with AJAX request you can do something like this:
request = new XMLHttpRequest;
request.open('GET', 'http://v-apps-campaign.com/dunkindonuts/main/get_allStore', true);
request.onload = function() {
if (request.status >= 200 && request.status < 400){
// Success!
data = JSON.parse(request.responseText);
} else {
// We reached our target server, but it returned an error
}
};
request.onerror = function() {
// There was a connection error of some sort
};
request.send();
your result will be in the data variable.
JSONP calls:
function getJSONP(url, callback) {
var script = document.createElement('script');
var callbackName = "jsonpcallback_" + new Date().getTime();
window[callbackName] = function (json) {
callback(json);
};
script.src = url + (url.indexOf("?") > -1 ? "&" : "?") + 'callback=' + callbackName;
document.getElementsByTagName('head')[0].appendChild(script);
}
getJSONP("http://v-apps-campaign.com/dunkindonuts/main/get_allStore", function(jsonObject){
//jsonObject is what you want
});
Regular ajax ajax call:
function getXHR() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
}
try {
return new ActiveXObject('MSXML2.XMLHTTP.6.0');
} catch (e) {
try {
// The fallback.
return new ActiveXObject('MSXML2.XMLHTTP.3.0');
} catch (e) {
throw new Error("This browser does not support XMLHttpRequest.");
}
}
}
function getJSON(url, callback) {
req = getXHR();
req.open("GET", url);
req.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var jsonObject = null,
status;
try {
jsonObject = JSON.parse(req.responseText);
status = "success";
} catch (e) {
status = "Invalid JSON string[" + e + "]";
}
callback(jsonObject, status, this);
}
};
req.onerror = function () {
callback(null, "error", null);
};
req.send(null);
}
getJSON("http://v-apps-campaign.com/dunkindonuts/main/get_allStore", function (jsonObject, status, xhr) {
//jsonObject is what you want
});
I tested these with your url and it seems like you should get the data with a jsonp call, because with regular ajax call it returns:
No 'Access-Control-Allow-Origin' header is present on the requested resource
with jsonp it gets the data but the data is not a valid json, it seems your server side has some php errors:
A PHP Error was encountered
...
In your HTML include your json file and a js code as modules
<script src="/locales/tshared.js" type="module" ></script>
<script src="/scripts/shared.js" type="module" ></script>
file content of tshared
export const loc = '{"en": { "key1": "Welcome" },"pt": {"key1": "Benvindo"} }'
file content of shared
import {loc} from "./../../locales/tshared.js";
var locale = null;
locale = JSON.parse(loc) ;
Adapt path and names as needed, use locale at will.

Categories