NSWI142: Web Applications

JavaScript client III.

Preliminaries

Please read this section at least one day prior to the seminar. This section outlines what you are expected to know, be able to do, or prepare in advance. Following these instructions will help you get the most out of the seminar and ensure smooth participation.

Preliminaries

Before the start of the practical, you should be able to:

  • Use JavaScript to create and manipulate with DOM in a browser.
  • Use JavaScript to listen for events.
  • Explain and use Promise and then/await.
  • Know how to use window.fetch function to perform HTTP GET request.

Preliminaries software

This slide applies to you only if you plan to use your own computer for the practical.

Before the start of the practical, make sure that:

  • You have a modern web browser.
  • An IDE with support for JavaScript would be nice.

Demonstration: Promise

Represents the eventual completion (then()) or failure (catch()) of an asynchronous operation. Promises can be chained.

The basics


      doSomethingAsynchronouslyAndReturnPromise()
        .then(result => transformResult(result);)
        .then(finalResult => console.log("Got the final result: " + finalResult);)
        .catch(failureCallback);
    

Alternative with "async" and "await".


      try {
        const result = await doSomethingAsynchronouslyAndReturnPromise();
        const finalResult = transformResult(result);
        console.log("Got the final result: " + finalResult);
      } catch (exception) {
        failureCallback();
      }
    

In browser you should use "await" only in an "async" function.

My own promise

You can create your own promise.


      function promiseMe() {
        return new Promise((resolve, reject) => {
          // TODO Make sure resolve or reject is called in future.
        });
      }
    

Benefit of a promise is that we can pass it around as a variable. As a result, we can decouple the place where we execute the asynch operation and where we wait for it.

Promise.

The Promise object provide functionality to use with promises.

For example you can use Promise.all() to wait for all given promises to resolve.

Demonstration: fetch

Data can be send encoded in URL (GET, POST, ..) or in request body (POST, PUT). We can send encoded JSON using the body or structure the content with FormData.

Making the request


      function fetchData(url) {
        fetch(url)
          // Use .text() to get text content.
          .then(response => response.json())
          .then(data => console.log("Got the data: " + data))
          .catch(error => console.log("Can't fetch data", error));
      }
    

Alternative implementation using async/await.


      async function fetchData() {
        try {
          const response = await fetch(url);
          // Use .text() to get text content.
          const data = await response.json();
          console.log("Got the data:", data);
        } catch(error) {
          console.log("Can't fetch data", error);
        }
      }
    

Cross-Origin Requests

Cross-origin network access (CORS) is using HTTP headers to control fetch. Below is an example of HTTP response headers allowing anyone to perform GET and POST.


      access-control-allow-methods: GET, OPTIONS
      access-control-allow-origin: *
    

CORS is implemented and enforced by browsers. Users are still able to execute a request by other means!

Cross-origin resource sharing (CORS) is the SELinux of the Web. You really want to do the right thing but it only works when you: "Access-Control-Allow-Origin", "*"

      // Is this working?
      await fetch("https://mff.cuni.cz/");
    

Exercise: Using fetch

The basics

Download a starting point website and implement missing functionality.

Be sure you understand what and why is happening in your solution.

Continue to the next slide once you are done.

Task Complete

Congratulations, if you have followed the instructions, you have just reached the end of this exercise.

Exercise: Model with fetch

Objective of this exercise is to finish the application from previous practicals.

Being optimistic

Continue with the bonus application from the last practical. Update the model to fetch products from the product list used in the previous exercise, ./service/api/v1/product/ . At this stage do not support the filters.

Continue to the next slide once you are done.

Filtering

There is no server side support for filtering, thus you need to implement the filters using the client side. Design and implement appropriate methods to make sure the filters are working again.

The idea is to fetch all the data at start then then filter them as users interacts with the application.

Continue to the next slide once you are done.

Handling errors

Make sure you application can handle errors.

If a request fail, repeat it once. If the request fail for the second time consider it to be a failed request.

If the list request fail, show an information to the user that the website is not working.

If the product detail request fail, just hide the product.

Continue to the next slide once you are done.

Waiting

As a request can take some time to complete you need to implement a loading indicator. To make it simple one main loading indicator is enough. So once you start making HTTP requests show a loading indicator to the user. Hide the loading indicator once all HTTP request are completed and only then show the data to the user.

You are allowed to use third-party CSS to create a loading indicator. For example you may consider CSS Loaders.

Task Complete

Congratulations, if you have followed the instructions, you have just reached the end of this exercise.

Questions, ideas, or any other feedback?

Please feel free to use the anonymous feedback form.