10.4 Using Browser APIs

In the last section, you learned how to use the fetch() method to access data from external APIs. In this section, you will instead make use of the browser APIs (sometimes also called Device APIs, and confusingly, also called Web APIs). These are APIs available to JavaScript developers that are provided by the browser.

In recent years, the amount of programmatic control available to the JavaScript developer has grown tremendously. You can now, for instance, retrieve location information, access synthesized voices, recognize and transcribe speech, and persist data content in the browser’s own local storage. Table 10.1 lists several of the more important browser APIs.

Table 10.1 Partial List of Browser APIs

Name Description
Canvas API Provides mechanism for drawing graphics within an HTML <canvas> element.
Device Orientation API Provides way to determine the orientation of the device.
Drag and Drop API Provides way to respond to drag and drop events from outside the browser.
Fullscreen API Allows an element to be displayed in full-screen mode (that is, without any browser chrome).
Gamepad API Provides way to access and respond to signals from gamepad input devices.
Geolocation API Provides mechanism for determining the location (latitude, longitude) of the user.
IndexDB API Provides mechanism for the client-side storage of significant amounts of structured data (including files).
Page Visibility API Provides events and methods for determining whether a page is visible.
Performance API Provides high-resolution timers for performing latency and timing evaluations.
Push API Provides events and methods for subscribing and responding to push-based messages.
Vibration API Provides access to vibration controls of mobile devices.
Web Speech API Allows a web page to incorporate voice data. It has two parts: SpeechSynthesis and SpeechRecognition.
Web Storage API Provides mechanism for storing key/value pairs. Also referred to simply as localStorage and sessionStorage.
Web Workers API Used for running a JavaScript operation in a background thread separate from the main execution thread of a web application, which can speed up perceived performance by running a laborious operation in the background.

Certainly there are too many browser APIs to cover in this chapter. The remainder of this section (and the accompanying lab) very briefly covers three of these APIs.

10.4.1 Web Storage API

The Web Storage API provides a mechanism for preserving non-essential state across requests and even across sessions. It comes in two varieties:

Using either of these is quite straightforward. To add a string to either involves calling the setItem() method of the localStorage or sessionStorage objects. To retrieve a value from either simply requires using the getItem() method. The following code example illustrates both:


let aValue = 'This is a sample string';
localStorage.setItem('aKey', aValue);
sessionStorage.setItem('aKey', aValue);
// now retrieve data
let something = localStorage.getItem('aKey');
let else = sessionStorage.getItem('aKey');

The user can examine (and delete) anything in localStorage or sessionStorage via the browser developer tools (for instance, in Chrome, this can be done via the Application tab within DevTools). Since this data can be removed, it is important to be able to handle the possibility that an expected key isn’t present. The following code illustrates how one might do this:


let something = localStorage.getItem('aKey');
if (! something) {
   // data doesn't exist in storage so handle this somehow
   something = defaultValue;
}

So why would you want to make use of this API? To improve the performance of a page. Perhaps the most common use case for localStorage is to keep a local copy of the data fetched from an external API. Listing 10.12 provides an example of its benefits. The code outputs the time taken to fetch a sample data set from an external API and the time taken to fetch it from localStorage. The difference is quite striking: 1150 milliseconds from the API, 3 milliseconds from localStorage in a typical run.

Notice also that localStorage can only store strings. So, if you wish to store data fetched from an API, it must be turned into a string first. In Listing 10.12, this is accomplished via JSON.stringify(). Similarly, when you retrieve the string from localStorage, it typically needs to be converted from a string into an object. In Listing 10.12, this is accomplished via JSON.parse().

Listing 10.12 Comparing retrieve performance of localStorage versus fetch


<h2>Examine console for timings</h2>
<button id="fromAPI">Load from API</button>
<button id="fromLocal">Load from localStorage</button>
<button id="removeLocal">Remove from localStorage</button>
<script>
document.querySelector("#fromAPI").addEventListener('click', async () => {
 const domain = "http://www.randyconnolly.com/funwebdev/3rd/api/movie";
 const url = domain + "/movies-brief.php?id=ALL";
   let t0 = performance.now();
   const response = await fetch(url);
   const movies = await response.json();
   let t1 = performance.now();
   // save the data as a JSON string
   localStorage.setItem('movies', JSON.stringify(movies));
   // outputs 1124 milliseconds
   console.log("fetching movies from API took " +
     (t1 - t0) + " milliseconds.")
});
document.querySelector("#fromLocal").addEventListener('click', () => {
   let t0 = performance.now();
   // retrieve JSON string and turn into array
   const movies = JSON.parse(localStorage.getItem('movies'))
   let t1 = performance.now();
   // outputs 3 milliseconds
   console.log("fetching movies from localStorage took " +
     (t1 - t0) + " milliseconds.")
});
document.querySelector("#removeLocal").addEventListener('click', () => {
   localStorage.removeItem('movies');
});
</script>

10.4.2 Web Speech API

The Web Speech API provides a mechanism for turning text into speech (sounds) and for turning speech (microphone input) into text. At the time of writing, the speech-to-text component uses a server-based recognition service, so is less widely used. Text to speech, on the other handle, is handled completely within the browser, so can be used with or without internet connectivity.

To verbalize a string of text, you can simply make use of the SpeechSynthesisUtterance and speechSynthesis objects:


const utterance = new SpeechSynthesisUtterance('Hello world');
speechSynthesis.speak(utterance);

Some browsers provide different voices: for instance, U.S. male, U.S. female, U.K. male, etc. You can also adjust the speed and pitch of the speech. The following code illustrates both:


let voices = speechSynthesis.getVoices();
let utterance = new SpeechSynthesisUtterance('Hello world');
utterance.voice = voices[3];
utterance.rate = 1.5;
utterance.pitch = 1.3;
speechSynthesis.speak(utterance);

10.4.3 GeoLocation

The Geolocation API provides a way for JavaScript to obtain the user’s location. For privacy protection, the browser will ask the user for permission before providing the location (that is, the latitude and longitude). Some devices (phones and tablets) have GPS functionality built in. Other devices (desktop computers) typically do not have GPS functionality. For those devices, the location will be very approximate based on what can be ascertained from a WiFi positioning system or the user’s IP address. For some users, this location information will be quite unhelpful, and only be the latitude and longitude of a city or even country.

Because geolocation may not be available (the user may have refused permission or the device does not support it), your code always needs to handle this possibility. Listing 10.13 illustrates a sample usage of this API:

Listing 10.13 Sample GeoLocation API usage


if (navigator.geolocation) {
   navigator.geolocation.getCurrentPosition(haveLocation,        geoError);
} else {
   // geolocation not supported or accepted
  ...
}
function haveLocation(position) {
    const latitude = position.coords.latitude;
    const longitude = position.coords.longitude;
    const altitude = position.coords.altitude;
    const accuracy = position.coords.accuracy;
    // now do something with this information
    ...
}
function geoError(error) { ... }