Руководство Javascript Fetch API

1- Обзор Fetch API

Обычно в программировании  Javascript  вам нужно получить данные из URL. Вы можете подумать об​ XMLHttpRequest API, это точно API, который поможет вам сделать то, что вы хотите, но он не будет дружественным и эффективным, потому что вам нужно писать длинные коды. Использовать  jQuery - это хорошая идея, синтаксис  jQuery.ajax(..) коротко и ясно, но вам нужно добавить библиотеку  jQuery в ваше приложение.
ES6 был представлен в июне 2015 года со многими новыми функциями, включая​​​​​​​ Promise. И Fetch API это новый стандарт для отправки запроса (request) на сервер и получения данных, назначение которого аналогично  XMLHttpRequest, разницей является  Fetch API написанный на основе концепции​​​​​​​ Promise.
Будет проще понять концепцию​​​​​​​ Promise ​​​​​​​прежде чем продолжить с этой статьей. Кроме того, я настоятельно рекомендую вам прочитать статью ниже, она абсолютно понятна всем.
Fetch API построил функцию  fetch(url,options) для получения данных из URL, данная функция возвращает  Promise, выглядит таким образом:
function fetch(url, options)  {

    // A Promise
    var aPromise = new Promise (
        function (resolve, reject) {

            if (allthingOK) {
               // ...
               var respone = ...;

               resolve(response);
            } else {
                var error = new Error('Error Cause');
                reject(error);
            }

        }
    );

    return aPromise;
}
И вы можете использовать  Fetch API довольно простым способом, нужно просто вызвать функцию  fetch(url,options) и получите обещание  решить (resolve) объект  response.
var url = "http://example.com/file";
var options = { method : 'GET', .... };

var aPromise = fetch(url, options);

aPromise
    .then(function(response) {
        
    })
    .catch(function(error) {
        
    });
var aPromise = fetch(url, {
    method: "GET", // POST, PUT, DELETE, etc.
    headers: {
        "Content-Type": "text/plain;charset=UTF-8" // for a string body, depends on body
    },
    body: undefined // string, FormData, Blob, BufferSource, or URLSearchParams
    referrer: "about:client", // "" for no-referrer, or an url from the current origin
    referrerPolicy: "no-referrer-when-downgrade", // no-referrer, origin, same-origin...
    mode: "cors", // same-origin, no-cors
    credentials: "same-origin", // omit, include
    cache: "default", // no-store, reload, no-cache, force-cache, or only-if-cached
    redirect: "follow", // manual, error
    integrity: "", // a hash, like "sha256-abcdef1234567890"
    keepalive: false, // true
    signal: undefined, // AbortController to abort request
    window: window // null
});

2- Get Text - response.text()

Используйте  Fetch API чтобы отправить запрос и получить текст, являющийся самой простой и понятной задачей.
This is a simple text data.
 
Функция  fetch(..) возвращает обещание решить (resolve) объект  response. Поэтому чтобы отправить запрос (request) для получения текстовых данных вам нужно выполнить шаг 1 следующим образом:
get-text-example.js (Step 1)
// A URL returns TEXT data.
var url = "https://rawgit.com/o7planning/webexamples/master/_testdatas_/simple-text-data.txt";


function doGetTEXT()  {

  // Call fetch(url) with default options.
  // It returns a Promise object (Resolve response object)
  var aPromise = fetch(url);

  // Work with Promise object:
  aPromise
    .then(function(response) {
        console.log("OK! Server returns a response object:");
        console.log(response);
    })
    .catch(function(error)  {
        console.log("Noooooo! Something error:");
        // Network Error!
        console.log(error);
    });

}
 
Метод  response.text() возвращает обещание разрешить объект  text, поэтому вы можете написать следующий код для данного примера таким образом:
get-text-example-way1.js
// A URL returns TEXT data.
var url = "https://rawgit.com/o7planning/webexamples/master/_testdatas_/simple-text-data.txt";


function doGetTEXT()  {

  // Call fetch(url) with default options.
  // It returns a Promise object (Resolve response object)
  var aPromise = fetch(url);

  // Work with Promise object:
  aPromise
    .then(function(response) {
        console.log("OK! Server returns a response object:");
        console.log(response);

        if(!response.ok)  {
            throw new Error("HTTP error, status = " + response.status);
        }

        response.text()
          .then(function(myText) {
               console.log("Text:");
               console.log(myText);
          })
          .catch(function(error) {
             // Never happened.
          });
    })
    .catch(function(error)  {
        console.log("Noooooo! Something error:");
        // Network Error!
        console.log(error);
    });
}
 
Fetch API был смоделирован, чтобы вы могли выполнять задачи по цепочке (Chain), это возможно потому что метод  promise.then(..), promise.catch(..) так же был смоделирован для возвращение обещания.
Даже если функция  function(response) которую вы написали возвращает обычное значение или возвращает объект  Promise, то метод  then() всегда возвращает Promise.
get-text-example-way2.js
// A URL returns TEXT data.
var url = "https://rawgit.com/o7planning/webexamples/master/_testdatas_/simple-text-data.txt";


function doGetTEXT()  {

  // Call fetch(url) with default options.
  // It returns a Promise object (Resolve response object)
  var aPromise = fetch(url);

  // Work with Promise object:
  aPromise
    .then(function(response) {
        console.log("OK! Server returns a response object:");
        console.log(response);

        if(!response.ok)  {
            throw new Error("HTTP error, status = " + response.status);
        }

        return response.text();
    })
    .then(function(myText)  {
         console.log("Text:");
         console.log(myText);
    })
    .catch(function(error)  {
        console.log("Noooooo! Something error:");
        // Network Error!
        console.log(error);
    });
}
 
get-text-example.html
<!DOCTYPE html>
<html>
<head>
    <title>fetch get text</title>
    <meta charset="UTF-8">

    <script src="get-text-example-way2.js"></script>
</head>
<body>

    <h3>fetch get text</h3>
    <p style="color:red">
         Click the button and see the results in the Console.
    </p>

    <button onclick="doGetJSON()">doGetJSON</button>

</body>
</html>

 

3- Get JSON - response.json()

Используйте  Fetch API чтобы отправить запрос и получить более сложный  JSON по сравнению с отправлением запроса для получения текста. Так как вам нужно обработать ошибки когда  JSON имеет неподходящий формат или данные  NULL.
json-simple-data.json
{
  "fullName" : "Tom Cat",
  "gender" : "Male",
  "address" : "Walt Disney"
}

 
Функция  fetch(..) возвращает обещание разрешить объект  response.
Шаг 1 (Step 1), напишите ваш код таким простым способом:
get-json-example.js (Step 1)
// A URL returns JSON data.
var url = "https://rawgit.com/o7planning/webexamples/master/_testdatas_/json-simple-data.json";


function doGetJSON()  {

  // Call fetch(url) with default options.
  // It returns a Promise object:
  var aPromise = fetch(url);

  // Work with Promise object:
  aPromise
    .then(function(response) {
        console.log("OK! Server returns a response object:");
        console.log(response);
    })
    .catch(function(error)  {
        console.log("Noooooo! Something error:");
        console.log(error);
    });

}

 

Way 1:

Метод  response.json() возвращает обещание разрешить (resolve) объект  JSON, поэтому вы можете использовать метод response.json().then(..).
get-json-example_way1.js
// A URL returns JSON data.
var url = "https://rawgit.com/o7planning/webexamples/master/_testdatas_/json-simple-data.json";


function doGetJSON()  {

  // Call fetch(url) with default options.
  // It returns a Promise object:
  var aPromise = fetch(url);

  // Work with Promise object:
  aPromise
    .then(function(response) {
        console.log("OK! Server returns a response object:");
        console.log(response);

        if(!response.ok) {
           throw new Error("HTTP error, status = " + response.status);
        }
        // Get JSON Promise from response object:
        var myJSON_promise = response.json();

        // Work with Promise object:
        myJSON_promise.then(function(myJSON))  {
          console.log("OK! JSON:");
          console.log(myJSON);
        }
    })
    .catch(function(error)  {
        console.log("Noooooo! Something error:");
        console.log(error);
    });

}
 

Way 2:

get-json-example-way2.js
// A URL returns JSON data.
var url = "https://rawgit.com/o7planning/webexamples/master/_testdatas_/json-simple-data.json";


function doGetJSON()  {

  // Call fetch(url) with default options.
  // It returns a Promise object:
  var aPromise = fetch(url);

  // Work with Promise object:
  aPromise
    .then(function(response) {
        console.log("OK! Server returns a response object:");
        console.log(response);

        if(!response.ok) {
           throw new Error("HTTP error, status = " + response.status);
        }
        // Get JSON Promise from response object:
        var myJSON_promise = response.json();

        // Returns a Promise object.
        return myJSON_promise;
    })
    .then(function(myJSON) {
        console.log("OK! JSON:");
        console.log(myJSON);
    })
    .catch(function(error)  {
        console.log("Noooooo! Something error:");
        console.log(error);
    });

}
 
get-json-example.html
<!DOCTYPE html>
<html>
<head>
    <title>fetch get json</title>
    <meta charset="UTF-8">

    <script src="get-json-example-way2.js"></script>
</head>
<body>

    <h3>fetch get json</h3>
    <p style="color:red">
         Click the button and see the results in the Console.
    </p>

    <button onclick="doGetJSON()">doGetJSON</button>

</body>
</html>
 

Null JSON Data?

Примечание: Метод  response.json() может выбросить ошибку, если ваш  URL возвращает данные, не являющиеся  JSON, или  JSON не действителен, или пустые данные.
Предположим, что вы отправили запрос (request) на получение информации о сотруднике по ID. Если сотрудник существует вы получите данные вида  JSON. И наоборот если сотрудник не существует вы получите данные  NULL. Но данные NULL вызывают ошибку там где вызывается  response.json(). Посмотрите пример:
  • http://example.com/employee?id=123

// Get information of Employee 123:
fetch("http://example.com/employee?id=123")
  .then(function(response) {
      console.log("OK! Server returns a response object:");
      console.log(response);

      if(!response.ok) {
         throw new Error("HTTP error, status = " + response.status);
      }

      // Error if Employee 123 does not exist.
      // (*** URL returns null).
      var myJSON_promise = response.json(); // =====> Error
      return myJSON_promise;
  })
  .then(function(myJSON) {
      console.log("OK! JSON:");
      console.log(myJSON);
  })
  .catch(function(error)  {
      console.log("Noooooo! Something error:");
      console.log(error);
  });
(Error)
SyntaxError: Unexpected end of JSON input
Используйте  response.text() вместо  response.json():
get-json-null-example.js
// A URL returns null JSON data.
var url = "https://rawgit.com/o7planning/webexamples/master/_testdatas_/json-null-data.json";


function doGetJSON()  {

  // Call fetch(url) with default options.
  // It returns a Promise object:
  var aPromise = fetch(url);

  // Work with Promise object:
  aPromise
    .then(function(response) {
        console.log("OK! Server returns a response object:");
        console.log(response);

        if(!response.ok) {
           throw new Error("HTTP error, status = " + response.status);
        }

        // Get TEXT Promise object from response object:
        var myText_promise = response.text();
        return myText_promise;
    })
    .then(function(myText) {
        console.log("OK! TEXT:");
        console.log(myText);

        var myJSON = null;

        if(myText != null && myText.trim().length > 0)  {
            myJSON = JSON.parse(myText);
        }
        console.log("OK! JSON:");
        console.log(myJSON);
    })
    .catch(function(error)  {
        console.log("Noooooo! Something error:");
        console.log(error);
    });

}
 
get-json-null-example.html
<!DOCTYPE html>
<html>
<head>
    <title>fetch get json</title>
    <meta charset="UTF-8">

    <script src="get-json-null-example.js"></script>
</head>
<body>

    <h3>fetch get null json</h3>
    <p style="color:red">
         Click the button and see the results in the Console.
    </p>

    <button onclick="doGetJSON()">doGetJSON</button>

</body>
</html>
 

4- Get Blob - response.blob()

Метод  response.blob() возвращает обещание разрешить (resolve) объект  Blob.
В примере ниже, я буду использовать  Fetch API для скачивания изображения, предоставленный с помощью  URL и отображения его на странице.
get-blob-example.js
// A URL returns Image data (Blob).
var url = "https://raw.githubusercontent.com/o7planning/webexamples/master/_testdatas_/triceratops.png";


function doGetBlob()  {

  // Call fetch(url) with default options.
  // It returns a Promise object:
  var aPromise = fetch(url);

  // Work with Promise object:
  aPromise
    .then(function(response) {
        console.log("OK! Server returns a response object:");
        console.log(response);

        if(!response.ok) {
           throw new Error("HTTP error, status = " + response.status);
        }
        // Get Blob Promise from response object:
        var myBlob_promise = response.blob();
        return myBlob_promise;
    })
    .then(function(myBlob) {
        console.log("OK! Blob:");
        console.log(myBlob);

        var objectURL = URL.createObjectURL(myBlob);
        var myImage = document.getElementById("my-img");
        myImage.src = objectURL;
    })
    .catch(function(error)  {
        console.log("Noooooo! Something error:");
        console.log(error);
    });

}
 
get-blob-example.html
<!DOCTYPE html>
<html>
<head>
    <title>fetch get blob</title>
    <meta charset="UTF-8">

    <script src="get-blob-example.js"></script>
</head>
<body>

    <h3>fetch get Blob</h3>
    <p style="color:red">
         Click the button to load Image.
    </p>

    <button onclick="doGetBlob()">doGetBlob</button>
    <br/>

    <img id="my-img" src="" height = 150 />

</body>
</html>

 

5- Get ArrayBuffer - response.arrayBuffer()

Метод  response.arrayBuffer() возвращает обещание разрешить (resolve) объект  ArrayBuffer.
Данные скачанные в виде буфера (buffer) помогают вам сразу работать с ними не дожидаясь скачивания всех данных, например тяжелый  Video, вы можете смотреть  Video когда его данные все еще загружаются на ваш браузер.
Пример ниже использует  Fetch API для воспроизведения файла музыки.
get-arraybuffer-example.js
// A URL returns Audio data.
var url = "https://raw.githubusercontent.com/o7planning/webexamples/master/_testdatas_/yodel.mp3";

// AudioContext
const audioContext = new AudioContext();
var bufferSource;

// Get ArrayBuffer (Audio data) and play it.
function doGetArrayBuffer()  {
  bufferSource = audioContext.createBufferSource();

  bufferSource.onended =  function () {
      document.getElementById("play").disabled=false;
  };

  // Call fetch(url) with default options.
  // It returns a Promise object:
  var aPromise = fetch(url);

  // Work with Promise object:
  var retPromise =
   aPromise
    .then(function(response) {

        if(!response.ok)  {
           throw new Error("HTTP error, status = " + response.status);
        }
        // Get ArrayBuffer Promise object from response object:
        var myArrayBuffer_promise = response.arrayBuffer();
        return myArrayBuffer_promise;
    })
    .then(function(myArrayBuffer) {

        audioContext.decodeAudioData(myArrayBuffer, function(decodedData) {
          bufferSource.buffer = decodedData;
          bufferSource.connect(audioContext.destination);
        });
    });

    return retPromise;
}

function playIt()  {
    console.clear();

    doGetArrayBuffer()
       .then(function() {
            document.getElementById("play").disabled=true;
            bufferSource.start(0);
       })
       .catch(function(error){
            alert("Something Error: " + error.message);
       });
}

function stopIt()  {
    bufferSource.stop(0);
    document.getElementById("play").disabled=false;
}
 
get-arraybuffer-example.html
<!DOCTYPE html>
<html>
<head>
    <title>fetch get ArrayBuffer</title>
    <meta charset="UTF-8">

    <script src="get-arraybuffer-example.js"></script>
</head>
<body>

    <h3>fetch get ArrayBuffer</h3>
    <p style="color:red">
         Click the button to play Audio.
    </p>

    <button onclick="playIt()" id="play">Play Audio</button>
    <button onclick="stopIt()" id="play">Stop Audio</button>

</body>
</html>

 
Web Audio API помогает вам работать с  Audio в среде web, он является большим  API связанный с  Fetch API. Если вам интересно, вы можете прочитать статью ниже:
  • TODO Link!

6- Get FormData - response.formData()

Метод  response.formData() возвращает обещание разрешить (resolve) объект  FormData. Вы часто используете данный метод в Service Workers. Когда пользователь отправляет данные Form на сервер, эти данные проходят через  Service Workers до того как доходят до сервера. В  Service Workers вы можете вызвать метод  response.formData(), и изменить значения в FormData если хотите.
  • TODO Link!