Validate if a file exists with JavaScript - javascript

Good day. I need to know if the file that I indicate in the path that I save in the text variable "t" as the slide variable "s" exist, in order to be able to show them or not through the view. I need to do this with only java script and local files, no server side. If possible, I would be very grateful to receive your help.
My current code in JavaScript:
function loadFiles(num) {
let s = 'assets/content/Compiladores/Slides/' + num + '.jpg';
let t = 'assets/content/Compiladores/Texts/' + num + '.txt';
document.slider.src = s;
$("#description").load(t);
$("#num").text(num);
}

You are never going to be able to reliably determine if a resource exists before doing something with it.
Note that this holds true even on a program that runs directly on a user's machine or a server. I don't normally mention other people's answers in my own, but the one advocating that you do that check (which per the link is problematic even in the best of circumstances) but across a client-server gap is sheer folly. Think about all the things that can go wrong:
The server could have moved the resource between the time you check and the time you set it.
Another thread or even entire other program could have acquired a lock on the resource causing your request to either take a lot of extra time or fail outright.
The user could be on a mobile connection and lost signal between the time of the check and the time of the resource request.
If you're passing an authentication token the user's session could expire between the time of the check and the time of the actual request.
The server could crash between the first request and the second.
The second request could be load-balanced to a different server than the first request.
The entire network for a major service could go down between the requests. Yes, really.
And so on.
Not to mention that for the happy path it involves a completely unnecessary extra round trip to the server before you start showing them the thing you wanted to show them in the first place!
The correct way to do this is to attempt to load the resource and then just handle the error if it fails:
function loadFiles(num) {
let s = 'assets/content/Compiladores/Slides/' + num + '.jpg';
let t = 'assets/content/Compiladores/Texts/' + num + '.txt';
document.slider.onerror = function () {
// deal with the resource not loading here
}
document.slider.src = s;
const desc = $("#description");
desc.on("error" function () {
// deal with the resource not loading here
});
desc.load(t);
$("#num").text(num);
}

try this for the file exists or not
function UrlExists(url)
{
var http = new XMLHttpRequest();
http.open('HEAD', url, false);
http.send();
return http.status!=404;
}
function UrlExists(url)
{
var http = new XMLHttpRequest();
http.open('HEAD', url, false);
http.send();
return http.status!=404;
}
function loadFiles(num) {
let s = 'assets/content/Compiladores/Slides/' + num + '.jpg';
let t = 'assets/content/Compiladores/Texts/' + num + '.txt';
document.slider.src = s;
if(UrlExists(s)){
$("#description").load(t);
}
if(UrlExists(t)){
$("#num").text(num);
}
}

Related

Trying to clear cache in Electron but it doesn't seem to work

Context: Adding a feature to an Electron app to check license data, etc. on start up by sending a query string using XMLHttpRequest to a remote server. In my testing rig, after a fresh launch an initial request will take 3-4 seconds but subsequent requests return immediately. That worries me.
So a caching issue? I haven't done much network stuff but searching around I saw this (How to clear the cache data in Electron(atom shell)?). Alas, it does not seem to make a difference. I have also tried adding a timestamp to the end of the query string to try to force a new request.
Am I doing something obviously wrong? I've upgraded to the latest version of Electron and have seen no difference.
function clearCache() {
var win = remote.getCurrentWindow();
win.webContents.session.clearStorageData(null, () => {
// this NEVER gets called
console.log('session cleared');
});
win.webContents.session.clearCache(function () {
// this DOES get called
console.log('cache cleared', (new Date()).getTime());
});
}
// attempt to force new request
var timestamp = (new Date()).getTime();
obj.timestamp = timestamp;
var url = domain + queryString.stringify(obj);
xhttp.open("GET", url);
xhttp.timeout = 1000 * 30;
xhttp.send();

Avoid XMLHttpRequest chain calling leak

In my code (a monitoring application) I need to periodically call the server with an XMLHttpRequest object in the form of chained calls. Each call takes exactly 15 seconds, which is timed by the server as it delivers several partial results within that period (HTTP 100 Continue). Immediately after finishing the current call, the onreadystatechange event handler of the current XMLHttpRequest object needs to create and launch the next request (with a new instance), so the communication with the server remains almost seamless.
The way it works, each call retains the object context of the caller in the stack, so as this is a page that must remain open for days, the stack keeps growing with no chance for the garbage collector to claim the data. See the following stack trace:
I cannot use timers (setInterval or such) to launch the next request. It should be launched from inside the ending of the previous one. The data from server must arrive as quickly as possible, and unfortunately browsers nowadays throtle timers when a page is not in focus. As I said, this is a monitoring application meant to be always on in the users' secondary monitors (rarely in focus). I also need to deal with HTTP timeouts and other kinds of errors that derail from the 15 second sequence. There should always be one and only one channel open with the server.
My question is whether is any way to avoid keeping the whole context in the stack when creating an XMLHttpRequest object. Even calling the click() method on a DOM object will keep the stack/context alive. Even promises seem to keep the context.
I'm also unable to use websockets, as the server does not support them.
UPDATE:
It's more complex, buy in essence it's like:
var xhttpObjUrl;
var xhttpObj;
onLoad() {
loadXMLDoc(pollURL + "first=1", true);
}
function loadXMLDoc(url, longtout) {
xhttpObjUrl = url;
xhttpObj = new XMLHttpRequest();
xhttpObj.open(method, url, true);
xhttpObj.onprogress = progress;
xhttpObj.onloadend = progress;
xhttpObj.ontimeout = progress;
if (commlog) consolelog("loadXMLDoc(): url == " + dname);
xhttpObj.send("");
}
function progress() {
if (!xhttpObj) return;
var state = xhttpObj.readyState;
var status;
var statusText;
if (state == 4 /* complete */ || state == 3 /* partial content */) {
try {
status = xhttpObj.status;
statusText = xhttpObj.statusText;
if (status == 200) parseServerData();
} catch (err) {
status = 500;
statusText = err;
}
if (state == 4 || status != 200) {
/* SERVER TERMINATES THE CONNECTION AFTER 15 SECONDS */
/* ERROR HANDLING REMOVED */
var obj = xhttpObj;
xhttpObj = undefined;
abortRequest(obj);
obj = false;
RequestEnd();
}
}
}
function RequestEnd(error) {
var now = (new Date).getTime();
var msdiff = now - lastreqstart;
var code = function () { loadXMLDoc(pollURL + 'lastpoint=' + evtprev.toString() + '&lastevent=' + evtcurrent.toString()); return false; };
if (msdiff < 1000) addTimedCheck(1, code); /** IGNORE THIS **/
else code();
}
I've solved my problem using a web worker. The worker would end the XMLHttpRequest each time and send the page a message with the collected data. Then, when the page finishes processing the data, it would send the worker a message to start a new request. Thus my page wouldn't have any unwanted delays between requests, and there's no stack constantly building up. On error I'd terminate the worker and create a new one, just in case.

image polling through javascript

I need to poll an image using javascript and need to perform an action once the image is found at its position. This is the code I have written for this task.
/*----Image handling script starts here----*/
var beacon = new Image();
beacon.onload = function() {
console.log('Image found');
console.log(this.width,this.height);
window.clearInterval(timer);
};
beacon.onerror = function(){
console.log('Image not found');
}
var timer = window.setInterval(function(){
console.log('sending the request again');
beacon.src = "http://www.google.co.in/logos/2010/lennon10-hp.gif";
},2000);
/*----Image handling script ends here----*/
Problem is that, after one GET request, the response gets cached and request don't get sent everytime I set src. If you examine NET tab, it sends request only on first src set and caches the response.
I need to send a fresh request for image every time my code sets the src. Any workarounds?
Change your src to include the current EPOCH time as a variable.
beacon.src = "http://www.google.co.in/logos/2010/lennon10-hp.gif?" +
date.getTime();
Using a different variable in the query string each time will miss out caching, because as far as the browser is concerned, the image is different (or potentially could be) each time you request the image, and there is no limit to the amount of times you ask, as time hopefully will not stop...
Request the image with a different query string each time. The browser will treat it as a unique URL and won't have it in the cache. You can probably get away with this because it's likely the web server will ignore anything in the query string when requesting an image. The following should make 100 requests:
for (var i=0; i<100; i++)
{
beacon.src = "http://www.google.co.in/logos/2010/lennon10-hp.gif?" + i;
}

Javascript: xmlhttprequest randomly stuck at Ready State 1

I've been working on a Windows gadget (meaning the "browser" is Internet Explorer) that queries specified subnet addresses for information. Now, it sometimes does this at a relatively quick pace (roughly every 5 seconds) and it works well enough. However, sometimes it will get stuck at ready state 1 and will just stay there forever. Whenever the gadget tries to redo the function for getting the xmlhttprequest and getting information from it it will stay at state 1. This is easily replicable when opening multiple instances of the gadget and then closing all but one of them. At that point, the one that's still open will almost always get stuck in this state. I feel like it might have something to do with them all accessing the same website, or it may just have to do with xmlhttprequests being stopped mid-transmission and that preventing another from working. Below is the relevant code.
//Reference to this for the inner function
var me = this;
var request = new XMLHttpRequest();
request.onreadystatechange = onReadyStateChange;
var url = this.url;
//Make the URL random to prevent being cached
url += ("&a=" + ((new Date()).getTime()));
Trace(DEBUG_COMM, "Sase.updateStatus url: " + url);
request.open("GET", url, true);
request.send(); // fire off the request, calls httpRequestReadyStateChange as things continue
Trace(DEBUG_COMM, "Request sent" + request.readyState);
function onReadyStateChange() {Trace(DEBUG_COMM, "Sase.httpRequestReadyStateChange: state=" + request.readyState);
if (4 == request.readyState) {
Trace(DEBUG_COMM, "Sase.httpRequestReadyStateChange: status=" + request.status);
if (request.status == 200) {
Trace(DEBUG_COMM, "retrieved html: " + request.responseText);
var results = request.responseText;
var resultsString = request.responseText.toString();
Trace(DEBUG_COMM, "results String: " + resultsString);
me.ParseStatusData(resultsString);
}
else {
//me.commError(request.status);
}
request = null;
}
}
Well it looks like I figured it out. I had a feeling it was an unresolved request, since it only happens when instances of it are closed (meaning that if one of them is closed while in communication with the server it stays in communication forever and no one else can access the server) and it appears that is the case. I made some modifications to the code in multiple areas and basically what it comes down to is when the gadget closes it makes sure to abort all of the requests. The requests are now instance variables (to allow for the aborting of them), but are still made new everytime they are needed.
For those who stumble across this and need a concrete code example, here you go.
I had the same problem and the solution was to re-use the XMLHttpRequest object, to ensure that any previous request was cancelled before initiating a new one. This won't work if you want to have multiple AJAX requests flying around but in my case triggering a new request meant that the last one was no longer needed.
All of the requests on my page went through the same XMLHttpRequest wrapper method which looked like this;
//Declare the XMLHttpRequest object to be re-used
var global_xHttpRequest = null;
function xmlHttpHandler(type, params, complete, postData) {
//Prevents an issue where previous requests get stuck and new ones then fail
if (global_xHttpRequest == null) {
global_xHttpRequest = new XMLHttpRequest();
} else {
global_xHttpRequest.abort();
}
//Parse out current URL
var baseURL = window.location.host;
var svc = "https://" + baseURL + "/processAction?";
var url = svc + params;
global_xHttpRequest.open(type, url, true);
//Add the callback
global_xHttpRequest.onreadystatechange = complete;
global_xHttpRequest.send(postData);
}
Which can be used like this:
xmlHttpHandler("GET", params, completeFnc);

Consecutive Ajax requests without jQuery/ JS library

I have an issue, mainly with IE.
I need to be able to handle n queries one after another. But If I simply call my function below in a for loop IE does some strange things (like loading only so many of the calls).
If I use an alert box it proves that the function gets all of the calls, and surprisingly IT WORKS!
My guess is that IE needs more time than other browsers, and the alert box does just that.
Here is my code:
var Ajax = function(all) {
this.xhr = new XMLHTTPREQUEST(); // Function returns xhr object/ activeX
this.uri = function(queries) { // Takes an object and formats query string
var qs = "", i = 0, len = size(queries);
for (value in queries) {
qs += value + "=" + queries[value];
if (++i <= len) { qs += "&"; }
}
return qs;
};
xhr.onreadystatechange = function() { // called when content is ready
if (this.readyState === 4) {
if (this.status === 200) {
all.success(this.responseText, all.params);
}
this.abort();
}
};
this.post = function() { // POST
xhr.open("POST", all.where, true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send(uri(all.queries));
};
this.get = function() { // GET
xhr.open("GET", all.where + "?" + uri(all.queries), true);
xhr.send();
};
if (this instanceof Ajax) {
return this.Ajax;
} else {
return new Ajax(all);
}
};
This function works perfectly for a single request, but how can I get it to work when called so many times within a loop?
I think the problem might be related to the 2 concurrent connections limit that most web browsers implement.
It looks like the latency of your web service to respond is making your AJAX requests overlap, which in turn is exceeding the 2 concurrent connections limit.
You may want to check out these articles regarding this limitation:
The Dreaded 2 Connection Limit
The Two HTTP Connection Limit Issue
Circumventing browser connection limits for fun and profit
This limit is also suggested in the HTTP spec: section 8.14 last paragraph, which is probably the main reason why most browsers impose it.
To work around this problem, you may want to consider the option of relaunching your AJAX request ONLY after a successful response from the previous AJAX call. This will prevent the overlap from happening. Consider the following example:
function autoUpdate () {
var ajaxConnection = new Ext.data.Connection();
ajaxConnection.request({
method: 'GET',
url: '/web-service/',
success: function (response) {
// Add your logic here for a successful AJAX response.
// ...
// ...
// Relaunch the autoUpdate() function in 100ms. (Could be less or more)
setTimeout(autoUpdate, 100);
}
}
}
This example uses ExtJS, but you could very easily use just XMLHttpRequest.
Given that the limit to a single domain is 2 concurrent connections in most browsers, it doesn't confer any speed advantage launching more than 2 concurrent requests. Launch 2 requests, and dequeue and launch another each time one completes.
I'd suggest throttling your requests so you only have a few (4?) outstanding at any given time. You're probably seeing the result of multiple requests being queued and timing out before your code can handle them all. Just a gess though. We have an ajax library that has built-in throttling and queues the requests so we only have 4 outstanding at any one time and don't see any problems. We routinely q lots per page.
Your code looks like it's put together using the constructor pattern. Are you invoking it with the new operator like var foo = new Ajax(...) in your calling code? Or are you just calling it directly like var foo = Ajax(...) ?
If the latter, you're likely overwriting state on your later calls. It looks like it's designed to be called to create an object, on which the get/post methods are called. This could be your problem if you're "calling it within a loop" as you say.

Categories

Resources