JavaScript Canvas - Fetch API
Written by Ian Elliot   
Tuesday, 16 July 2024
Article Index
JavaScript Canvas - Fetch API
Working with the Server - Basic Fetch
Request Object

Working with the Server - Basic Fetch

We can use the file input tag and the fileReader to read files on the local machine and the HTMLAnchorElement object to save them. Getting files from the remote file system, i.e. the server, is a much more common operation. We have already seen how to use the Image object to load any supported graphics file under program control. Sometimes, however, we need to access a file more directly.

The Fetch API is an implementation of the XMLHttpRequest object and can be used to download almost any file the browser has access to, and to send data to the server using GET or POST HTTP methods. You can still use XMLHttpRequest, but fetch is the modern way to do things and this is what will be described in this chapter.

The basic idea is really simple. All you have to do is use:

fetch(“URL”);

This performs a GET request for the URL specified and returns a Promise that eventually resolves to a Response object. The fetch function is available in the Window and WorkerGlobal contexts. Also notice that you can use the URL object to construct the URL you need to use, or you can simply use a string.

Most HTTP errors are also returned as a resolved promise and a response object that specifies the error. The reject state is reserved for communications errors. This means that you can use try-catch to deal with communications problems but you have to check the response object for “soft” errors.

You could use the promise’s then method to specify what happens to the response, but it is much simpler to use async and await:

async function getText(){
	var response=await fetch('myFile.txt');

For a simple file retrieval this is almost all there is to using fetch. The response object returned has a set of methods and properties that allow you to discover the status of the request and retrieve the data.

For example, the status property returns the HTTP status code – usually 200. As already mentioned HTTP errors such as 404 no such page are returned as resolved promises and you have to handle them as errors. You only get a rejected promise if there is something wrong that is more reasonably characterized as an exception. You can also retrieve the headers sent from the server using the headers property which returns a Headers object.

Notice that at this stage we only have the HTTP headers and status, the data are still to be fetched across the network.

The Response.body gives you access to a readable stream. This allows you to read the data in a chunk at a time. This is useful when, for example, you are trying to work with something that is too big to fit in memory or when data is being continuously generated. The Streams API is another new feature that makes use of Promises. To read the Response in chunks you would use something like:

var reader=Response.body.getReader();

Following this each time you use the read method a promise which resolves to the next chunk of the stream is returned:

var data=await reader.read();

The data is of the form:

{value:chunk,done:boolean}

where value is the data and done is true if this is the last chunk of data. You also need to know that a stream can only be read once unless it is recreated.

Streams are very low-level compared to what most people want to do with retrieved resources. For this reason the Body object also implements a set of higher-level stream readers. These return a Promise that resolves after the entire stream has been read to the data in a processed format.

As already explained, the currently supplied formatted readers are arrayBuffer, blobform, Datajson, and text and each returns a Promise which resolves to the type of data you have selected.

One subtle point is that you can only retrieve a response’s data once. This is obvious if you keep in mind that the methods that retrieve the data are stream readers and you can only read a stream to the end once. However, it can cause problems if you mistakenly think of these methods as simply providing format conversion.

Consider, for example:

async function getText(){ 
	var response=await fetch('myFile.txt');
console.log(response.status); console.log(await response.text()); }

This retrieves the data in the file as text. Once the response body has been retrieved or “used” you cannot repeat the operation. That is:

async function getText(){ 
	var response=await fetch('myFile.txt');
console.log(response.status); console.log(await response.text());
console.log(await response.text()); }

throws the exception:

Uncaught (in promise) TypeError: Already read

You can check to see if the body has been used via the bodyUsed property of either the request or the response. If you do want to access the data in more than one format then you have to make use of the clone method – see later.

smallcover180

 



Last Updated ( Wednesday, 17 July 2024 )