MT IT
  • Introduction
  • KEEP IN MIND!!
  • 1️⃣1st month
    • Week 1
      • HTML/CSS
        • HTML
          • HTML Dasar
          • HTML Layouting
          • Learn More
            • Semantic HTML
            • Tables
            • Videos
            • Images
        • CSS
          • CSS Dasar
      • Weekly Review
    • Week 2
      • Bootstrap
        • Tutorial Bootstrap 5
      • Git & Github
      • Responsive
        • Responsive with Bootstrap 5
      • Weekly Review
    • Week 3
      • Javascript
        • Introduction to Javascript
          • What is JavaScript?
          • Brief History of JavaScript
          • How To Add JavaScript to HTML
        • All About Variables
          • Variables
          • Naming JavaScript Variables
          • JavaScript Naming Conventions
          • JavaScript Scope
        • Datatypes
          • What are data types?
          • Primitives and objects
          • Primitive data types
          • Object data types
          • TypeOf Operator
      • Weekly Review
    • Week 4
      • Javascript
        • Data Structures
          • Keyed Collections
          • Indexed collections
        • Equality Comparisons
        • Loops and Iterations
          • The for loop
          • do…while statement
          • while statement
      • Weekly Review
    • Monthly Review
  • 2️⃣2nd Month
    • Week 5
      • Javascript
        • Expressions and Operators
          • Basic operators, maths
          • Assignment operators
          • Comparison operators
          • Logical operators
          • String operators
          • Conditional (ternary) operator
          • Comma operator
        • JavaScript Function
        • Arrow function expressions
        • Built in functions
      • REST - Representational State Transfer
        • API - Application Programming Interface
        • Fetching data from the server
        • The Fetch API
        • Cross-Origin Resource Sharing (CORS)
      • Weekly Review
    • Week 6
      • DOM (Document Object Model)
        • DOM tree
        • Selecting elements
          • getElementById()
          • getElementsByName()
          • querySelector()
        • Manipulating elements
          • createElement()
          • appendChild()
          • textContent
        • Working with Attributes
          • Understanding Relationships Between HTML Attributes & DOM Object’s Properties
          • setAttribute()
          • getAttribute()
          • removeAttribute()
          • hasAttribute()
        • Manipulating Element’s Styles
          • JavaScript Style
          • getComputedStyle()
          • className
          • classList
          • Getting the Width and Height of an Element
        • Working with Events
          • JavaScript Events
          • Handling Events
          • Page Load Events
          • onload
          • Mouse Events
          • Keyboard Events
          • Scroll Events
          • scrollIntoView
      • React JS
        • Getting Started
        • Components Basics
          • Introducing JSX
          • Writing Markup with JSX
          • React Function Components
          • Props vs State
            • State: A Component's Memory
            • How to use Props in React
      • Working with APIs - 1
        • XMLHttpRequest
        • Fetch
      • Weekly Review
    • Week 7
      • Javascript
        • Asynchronous JavaScript
          • Asynchronous JavaScript For Dummies
            • (Pt1): Internals Disclosed!
            • (Pt2): Callbacks
            • (Pt3): Promises
            • (Pt4): Async/Await
        • Callback
        • Promises
          • Promises Basics
          • Promises Chaining
          • Promises Error Handling
        • Async/await
          • async function
        • Tutorial – Learn Callbacks, Promises, & Async/Await in JS by Making Ice Cream
      • React JS
        • Rendering
          • Conditional Rendering
          • Lists and Keys
          • Render Props
        • Hooks
          • useState
          • useEffect
      • Working with APIs - 2
        • Axios
      • React Router Dom
      • Weekly Review
    • Week 8
      • React JS
      • Responsive
      • Chakra UI
      • Firebase
        • Firebase Authentication
      • Weekly Review
    • Monthly Review
  • 3️⃣3rd month
    • Week 9
      • React JS
      • Chakra UI
      • Firebase
      • Axios
      • Weekly Review
    • Week 10
      • React JS
      • Boilerplate
      • Weekly Review
    • Week 11
      • Projects
      • Weekly Review
    • Week 12
      • Projects
      • Weekly Review
    • Project Review
  • 🏁FINAL REVIEW
  • 👇!! Learn More Below !!
  • 🥸Frontend Stack
    • 💻Web Dev
      • React JS
        • Reactstrap
        • React Icons
        • React Router Dom
      • Chakra UI
    • 📱Mobile Dev
      • React Native
        • Introduction
        • Page 1
      • Expo
      • Nativebase
    • 🎽CSS
      • Tailwind
      • Bootstrap
  • ☕Backend Stack
    • Node JS
    • Firebase
      • Authentication
      • Firestore
      • Storage
      • Hosting
      • Cloud Function
      • Emulators
      • RTDB
      • FCM
    • Google Cloud Platform
      • AppEngine
      • Big Query
      • Cloud Functions
      • Cloud Run
      • Cloud Scheduler
      • Cloud SQL
      • Logging
    • Object Relational Mapping (ORM)
      • Sequelize
    • MongoDB
      • MongoDB Realm
    • MySQL
      • Introduction
  • 🦸Fullstack
    • NEXT JS
    • LARAVEL
  • 📦Package
    • Middleware
      • Express JS
    • HTTP client
      • AXIOS
    • 📊Chart
      • Chart.js
      • JSCharting
      • React Google Chart
    • ⏳Date & Time
      • Moment JS
      • Day JS
    • 👨‍💻WYSIWYG Editor
      • Quill JS
      • Slate JS
Powered by GitBook
On this page
  • Response headers
  • Request headers
  • POST requests
  • Sending an image
  • Summary
  1. 2nd Month
  2. Week 6
  3. Working with APIs - 1

Fetch

JavaScript can send network requests to the server and load new information whenever it’s needed.

For example, we can use a network request to:

  • Submit an order,

  • Load user information,

  • Receive latest updates from the server,

  • …etc.

…And all of that without reloading the page!

There’s an umbrella term “AJAX” (abbreviated Asynchronous JavaScript And XML) for network requests from JavaScript. We don’t have to use XML though: the term comes from old times, that’s why that word is there. You may have heard that term already.

There are multiple ways to send a network request and get information from the server.

The fetch() method is modern and versatile, so we’ll start with it. It’s not supported by old browsers (can be polyfilled), but very well supported among the modern ones.

The basic syntax is:

let promise = fetch(url, [options])
  • url – the URL to access.

  • options – optional parameters: method, headers etc.

Without options, this is a simple GET request, downloading the contents of the url.

The browser starts the request right away and returns a promise that the calling code should use to get the result.

Getting a response is usually a two-stage process.

At this stage we can check HTTP status, to see whether it is successful or not, check headers, but don’t have the body yet.

The promise rejects if the fetch was unable to make HTTP-request, e.g. network problems, or there’s no such site. Abnormal HTTP-statuses, such as 404 or 500 do not cause an error.

We can see HTTP-status in response properties:

  • status – HTTP status code, e.g. 200.

  • ok – boolean, true if the HTTP status code is 200-299.

For example:

let response = await fetch(url);

if (response.ok) { // if HTTP-status is 200-299
  // get the response body (the method explained below)
  let json = await response.json();
} else {
  alert("HTTP-Error: " + response.status);
}

Second, to get the response body, we need to use an additional method call.

Response provides multiple promise-based methods to access the body in various formats:

  • response.text() – read the response and return as text,

  • response.json() – parse the response as JSON,

For instance, let’s get a JSON-object with latest commits from GitHub:

let url = 'https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits';
let response = await fetch(url);

let commits = await response.json(); // read response body and parse as JSON

alert(commits[0].author.login);

Or, the same without await, using pure promises syntax:

fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits')
  .then(response => response.json())
  .then(commits => alert(commits[0].author.login));

To get the response text, await response.text() instead of .json():

let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits');

let text = await response.text(); // read response body as text

alert(text.slice(0, 80) + '...');
let response = await fetch('/article/fetch/logo-fetch.svg');

let blob = await response.blob(); // download as Blob object

// create <img> for it
let img = document.createElement('img');
img.style = 'position:fixed;top:10px;left:10px;width:100px';
document.body.append(img);

// show it
img.src = URL.createObjectURL(blob);

setTimeout(() => { // hide after three seconds
  img.remove();
  URL.revokeObjectURL(img.src);
}, 3000);

Important:

We can choose only one body-reading method.

If we’ve already got the response with response.text(), then response.json() won’t work, as the body content has already been processed.

let text = await response.text(); // response body consumed
let parsed = await response.json(); // fails (already consumed)

The response headers are available in a Map-like headers object in response.headers.

It’s not exactly a Map, but it has similar methods to get individual headers by name or iterate over them:

let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits');

// get one header
alert(response.headers.get('Content-Type')); // application/json; charset=utf-8

// iterate over all headers
for (let [key, value] of response.headers) {
  alert(`${key} = ${value}`);
}

To set a request header in fetch, we can use the headers option. It has an object with outgoing headers, like this:

let response = fetch(protectedUrl, {
  headers: {
    Authentication: 'secret'
  }
});
  • Accept-Charset, Accept-Encoding

  • Access-Control-Request-Headers

  • Access-Control-Request-Method

  • Connection

  • Content-Length

  • Cookie, Cookie2

  • Date

  • DNT

  • Expect

  • Host

  • Keep-Alive

  • Origin

  • Referer

  • TE

  • Trailer

  • Transfer-Encoding

  • Upgrade

  • Via

  • Proxy-*

  • Sec-*

These headers ensure proper and safe HTTP, so they are controlled exclusively by the browser.

To make a POST request, or a request with another method, we need to use fetch options:

  • method – HTTP-method, e.g. POST,

  • body – the request body, one of:

    • a string (e.g. JSON-encoded),

    • FormData object, to submit the data as multipart/form-data,

    • Blob/BufferSource to send binary data,

The JSON format is used most of the time.

For example, this code submits user object as JSON:

let user = {
  name: 'John',
  surname: 'Smith'
};

let response = await fetch('/article/fetch/post/user', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  },
  body: JSON.stringify(user)
});

let result = await response.json();
alert(result.message);

Please note, if the request body is a string, then Content-Type header is set to text/plain;charset=UTF-8 by default.

But, as we’re going to send JSON, we use headers option to send application/json instead, the correct Content-Type for JSON-encoded data.

We can also submit binary data with fetch using Blob or BufferSource objects.

In this example, there’s a <canvas> where we can draw by moving a mouse over it. A click on the “submit” button sends the image to the server:

<body style="margin:0">
  <canvas id="canvasElem" width="100" height="80" style="border:1px solid"></canvas>

  <input type="button" value="Submit" onclick="submit()">

  <script>
    canvasElem.onmousemove = function(e) {
      let ctx = canvasElem.getContext('2d');
      ctx.lineTo(e.clientX, e.clientY);
      ctx.stroke();
    };

    async function submit() {
      let blob = await new Promise(resolve => canvasElem.toBlob(resolve, 'image/png'));
      let response = await fetch('/article/fetch/post/image', {
        method: 'POST',
        body: blob
      });

      // the server responds with confirmation and the image size
      let result = await response.json();
      alert(result.message);
    }

  </script>
</body>

Please note, here we don’t set Content-Type header manually, because a Blob object has a built-in type (here image/png, as generated by toBlob). For Blob objects that type becomes the value of Content-Type.

The submit() function can be rewritten without async/await like this:

function submit() {
  canvasElem.toBlob(function(blob) {
    fetch('/article/fetch/post/image', {
      method: 'POST',
      body: blob
    })
      .then(response => response.json())
      .then(result => alert(JSON.stringify(result, null, 2)))
  }, 'image/png');
}

A typical fetch request consists of two await calls:

let response = await fetch(url, options); // resolves with response headers
let result = await response.json(); // read body as json

Or, without await:

fetch(url, options)
  .then(response => response.json())
  .then(result => /* process result */)

Response properties:

  • response.status – HTTP code of the response,

  • response.ok – true if the status is 200-299.

  • response.headers – Map-like object with HTTP headers.

Methods to get response body:

  • response.text() – return the response as text,

  • response.json() – parse the response as JSON object,

  • response.formData() – return the response as FormData object (multipart/form-data encoding, see the next chapter),

Fetch options so far:

  • method – HTTP-method,

  • headers – an object with request headers (not any header is allowed),

  • body – the data to send (request body) as string, FormData, BufferSource, Blob or UrlSearchParams object.

PreviousXMLHttpRequestNextWeekly Review

Last updated 1 year ago

First, the promise, returned by fetch, resolves with an object of the built-in class as soon as the server responds with headers.

response.formData() – return the response as FormData object (explained in the ),

response.blob() – return the response as (binary data with type),

response.arrayBuffer() – return the response as (low-level representation of binary data),

additionally, response.body is a object, it allows you to read the body chunk-by-chunk, we’ll see an example later.

As a show-case for reading in binary format, let’s fetch and show a logo image of (see chapter for details about operations on Blob):

…But there’s a list of that we can’t set:

, to submit the data in x-www-form-urlencoded encoding, rarely used.

response.blob() – return the response as (binary data with type),

response.arrayBuffer() – return the response as (low-level binary data),

2️⃣
Response
next chapter
Blob
ArrayBuffer
ReadableStream
“fetch” specification
Blob
Response headers
Request headers
forbidden HTTP headers
POST requests
URLSearchParams
Sending an image
Summary
Blob
ArrayBuffer