<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>fetch() promise.finally() example</title>
  </head>
  <body>
    <script>
      // Define function to fetch a file and return it in a usable form
      function fetchAndDecode(url, type) {
        // Returning the top level promise, so the result of the entire chain is returned out of the function
        return fetch(url).then(response => {
          // Depending on what type of file is being fetched, use the relevant function to decode its contents
          if(type === 'blob') {
            return response.blob();
          } else if(type === 'text') {
            return response.text();
          }
        })
        .catch(e => {
          console.log(`There has been a problem with your fetch operation for resource "${url}": ` + e.message);
        })
        .finally(() => {
          console.log(`fetch attempt for "${url}" finished.`);
        });
      }

      // Call the fetchAndDecode() method to fetch the images and the text, and store their promises in variables
      let coffee = fetchAndDecode('coffee.jpg', 'blob');
      let tea = fetchAndDecode('tea.jpg', 'blob');
      let description = fetchAndDecode('description.txt', 'text');

      // Use Promise.all() to run code only when all three function calls have resolved
      Promise.all([coffee, tea, description]).then(values => {
        console.log(values);
        // Store each value returned from the promises in separate variables; create object URLs from the blobs
        let objectURL1 = URL.createObjectURL(values[0]);
        let objectURL2 = URL.createObjectURL(values[1]);
        let descText = values[2];

        // Display the images in <img> elements
        let image1 = document.createElement('img');
        let image2 = document.createElement('img');
        image1.src = objectURL1;
        image2.src = objectURL2;
        document.body.appendChild(image1);
        document.body.appendChild(image2);

        // Display the text in a paragraph
        let para = document.createElement('p');
        para.textContent = descText;
        document.body.appendChild(para);
      });
    </script>
  </body>
</html>
