Why this image access loading error on a Promise script fiddle? - javascript

I'm using a Promise to load an image in a fiddle and keep getting an access error. I've tried a variety of images - posted to dropbox, placeholders, and others, but all are blocked. What can I use/do that will work? I believe the question and answer here are relevant, but am having trouble connecting the dots.
Here is the error:
XMLHttpRequest cannot load https://www.dropbox.com/s/i7ptcure9tlw8pl/Pensive%20Parakeet.jpg?dl=0. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://fiddle.jshell.net' is therefore not allowed access.
I'm using the fiddle to practice writing Promises to get my head around them, and have borrowed the script here to practice on. My fiddle in question is here.

As I explained in my comment that URL from dropbox doesn't allow cross-origin requests plus the resource isn't an image (it's actually html). If you use images from a site that allows cross-origin requests (like imgur for example) then it works.
function imgLoad(url) {
// Create new promise with the Promise() constructor;
// This has as its argument a function
// with two parameters, resolve and reject
return new Promise(function(resolve, reject) {
// Standard XHR to load an image
var request = new XMLHttpRequest();
request.open('GET', url);
request.responseType = 'blob';
// When the request loads, check whether it was successful
request.onload = function() {
if (request.status === 200) {
// If successful, resolve the promise by passing back the request response
resolve(request.response);
} else {
// If it fails, reject the promise with a error message
reject(Error('Image didn\'t load successfully; error code:' + request.statusText));
}
};
request.onerror = function() {
// Also deal with the case when the entire request fails to begin with
// This is probably a network error, so reject the promise with an appropriate message
reject(Error('There was a network error.'));
};
// Send the request
request.send();
});
}
// Get a reference to the body element, and create a new image object
var body = document.querySelector('body');
var myImage = new Image();
// Call the function with the URL we want to load, but then chain the
// promise then() method on to the end of it. This contains two callbacks
imgLoad('https://i.imgur.com/Kusegys.jpg').then(function(response) {
// The first runs when the promise resolves, with the request.reponse
// specified within the resolve() method.
var imageURL = window.URL.createObjectURL(response);
myImage.src = imageURL;
body.appendChild(myImage);
// The second runs when the promise
// is rejected, and logs the Error specified with the reject() method.
}, function(Error) {
console.log(Error);
});
img {
height:1125px;
width:750px;
}

Related

What is the difference between timeout and error in XMLHttpRequest?

Can somebody please explain me when error and ehen timeout error will be raised.
I put timeout here for PUT request but in what use case will be called onTimeout and in what onError handlers?
return new Promise(async function(resolve, reject) {
const xhr = new XMLHttpRequest();
xhr.open("PUT", url);
xhr.timeout = 10000;
xhr.onreadystatechange = async function() {
....
}
xhr.ontimeout = function() {
// Time out.
};
xhr.onerror = function() {
// Some error
};
}
The XMLHttpRequest.timeout property is an unsigned long representing the number of milliseconds a request can take before automatically being terminated. The default value is 0, which means there is no timeout. Timeout shouldn't be used for synchronous XMLHttpRequests requests used in a document environment or it will throw an InvalidAccessError exception. When a timeout happens, a timeout event is fired.
Despite the request timeout onerror method fires right after server has sent the error response. For example, if your server is shut down your timeout method will be fired after 10 seconds.
More info: here

Making a CORS request to Google Static Maps

I'm trying to make a CORS request to Google's static maps api and return an image to be mounted on canvas (to avoid canvas's Cross Origin protection). I'm not sure if I'm following the instructions correctly (https://developers.google.com/api-client-library/javascript/features/cors) but the xhr request never returns anything.
const position = latLngArg;
var xhr = new XMLHttpRequest();
xhr.open('GET',
`http://maps.googleapis.com/maps/api/staticmap?center=${position.lat()},${position.lng()}&zoom=20&size=20x20&maptype=roadmap&sensor=false&key=AIzaSyBiE2efHKeAptVfVRtj9-ZDeHWPKgNjdNk`)
.then(...)
The XMLHttlRequest open method does not return a promise.
It also does not send the request it only initialize it. In order to set the request you need to call the send method afterwards.
You should register a callback to be triggered upon success by setting the onreadystatechange property.
See an example here.
Native XHR do not work with promises.
You can try the following:
const position = latLngArg;
const xhr = new XMLHttpRequest();
const address = `http://maps.googleapis.com/maps/api/staticmap?center=${position.lat()},${position.lng()}&zoom=20&size=20x20&maptype=roadmap&sensor=false&key=AIzaSyBiE2efHKeAptVfVRtj9-ZDeHWPKgNjdNk`;
xhr.open('GET', address);
xhr.onload = () => onImageReceived(xhr.response);
xhr.send();
function onImageReceived(image) {
console.log(image);
}
You can verify that the xhr.response will be your image, after the request was completed (onload event).
Read more about it here.

Detect specific error (403) with JS

I'm attempting to catch a potential error on my page, the page has a collection of URLs (retrieved at page load) to various resources which are loaded when needed.
However these resources are only available for a set time, so if the user leaves the page idle for a long period, the URLs may no longer be valid and may return a 403.
I'm currently detecting errors on the resources using something along the lines of:
$(".identifier").on("error", function () {
console.log("Error on resource load");
});
But can I detect the specific type of error / the error code? e.g. the 403 permissions error rather than a generic "There is an error". If possible I would like to be able to react differently to different errors.
Let's say you have all available URL's to your resources inside an array e.g.
var resources = [
"http://url/to/resource-one.fiel",
"http://url/to/resource-two.fiel"
]
Then you could use the following function to check the http response of these resources, by looping over the array and passing each resource to checkResources.
function checkResource (url, index) {
var req = new XMLHttpRequest();
req.open('HEAD', url, true);
req.send();
if (req.status === 404) {
return index;
}
if (req.status === 403) {
return index;
}
};
Or use a specific URL without a loop and delete the index param in the function,
maybe return the URL instead. In other words do an ajax HEAD request, which will only return the headers resource, rather than the resource itself.
You could as well get all the header information or just a specific header info by name like so
xmlhttp.open('HEAD', 'path/to/your/resource', true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
console.log(xmlhttp.getAllResponseHeaders()); // get all header info
console.log(xmlhttp.getResponseHeader("Last-Modified")); // get by name
}
}
xmlhttp.send(null)

Load error is not captured by try catch block

I have a code like:
try{
...
} catch(error){
...
};
In try block, there is a function call that makes a request to a server. When there is no resource on the server, an error is raised (as I can see in Google Chrome's developers tool):
Failed to load resource: the server responded with a status of 404 (Not Found)
and I am trying to catch it in the catch block, but the error is not captured.
Is it a feature of JavaScript that load error is not captured by try catch block?
Typically, when requesting information from a server (for instance, via ajax, by setting the src of an img element, etc.), you don't get an exception, but you do get an error event or callback, not least because the code doing the request finishes before the request does, so it's impossible to throw an exception at that point. Since you haven't shown how you're requesting the information, it's impossible to be more specific, but this is why you're not getting an exception.
For instance, with an ajax request, if there's an error you see the ajax request complete but with the statusCode of the XMLHttpRequest object being an error status code, rather than 200. E.g.:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
// The request is complete; did it work?
if (xhr.statusCode >= 200 && xhr.statusCode < 300) {
// Yes
}
else {
// No, got a code outside the 2xx range
}
}
};
xhr.open("GET", "/your/url/here", true);
xhr.send();

HTTP HEAD Request in Javascript/Ajax?

Is it possible to do a HTTP Head request solely using an XMLHTTPRequest in JavaScript?
My motivation is to conserve bandwidth.
If not, is it possible to fake it?
Easy, just use the HEAD method, instead of GET or POST:
function UrlExists(url, callback)
{
var http = new XMLHttpRequest();
http.open('HEAD', url);
http.onreadystatechange = function() {
if (this.readyState == this.DONE) {
callback(this.status != 404);
}
};
http.send();
}
This is just a short example to show how to use the HEAD method. Production code may need more fine-grained callbacks for different result states (success, failure, timeout), and may use different event handlers (onload, onerror and ontimeout rather than onreadystatechange).
An XMLHTTPRequest object should have
getAllResponseHeaders();
getResponseHeader("header-name")
defined on it

Categories

Resources