Usando Fetch
============

A API Fetch fornece uma interface JavaScript para acessar e manipular partes do pipeline HTTP, tais como os pedidos e respostas. Ela também fornece o método global `fetch()` (en-US) que fornece uma maneira fácil e lógica para buscar recursos de forma assíncrona através da rede.

Este tipo de funcionalidade era obtida anteriormente utilizando `XMLHttpRequest`. Fetch fornece uma alternativa melhor que pode ser facilmente utilizada por outras tecnologias como `Service Workers` (en-US). Fetch também provê um lugar lógico único para definir outros conceitos relacionados ao protocolo HTTP como CORS e extensões ao HTTP.

Note que a especificação `fetch()` difere de `jQuery.ajax()`, principalmente, de três formas:

* A Promise retornada do `fetch()` **não rejeitará o status do erro HTTP,** mesmo que a resposta seja um HTTP 404 ou 500. Em vez disso, ela irá resolver normalmente (com o status `ok` definido como falso), e só irá rejeitar se houver falha na rede ou se algo impedir a requisição de ser completada.
* `fetch()` **não receberá cookies cross-site;** você não pode estabelecer uma conexão cross-site usando fetch. Cabeçalhos `Set-Cookie` de outros sites são ignorados silenciosamente.
* `fetch()` **não enviará cookies**, a não ser que seja definida a opção *credentials* do parâmetro init. (Desde 25 de agosto de 2017. A especificação alterou as políticas padrão de credenciais para `same-origin`. O Firefox mudou desde 61.0b13.)
Situação do suporte por navegadores
-----------------------------------

Os suportes para Fetch ainda estão em uma fase bastante precoce, mas começa a ter progresso. Se tornou um padrão no Firefox 39 e Chrome 42 até as versões mais atuais.

Caso tenha interesse no uso da ferramenta, há também uma Fetch Polyfill disponivel que recria as funcionalidade para outros navegadores que ainda não o suporta. Fique ciente que está em estado experimental e ainda não há uma versão completa.

**Nota:** There have been some concerns raised that the Fetch spec is at odds with the Streams spec; however, future plans show an intention to integrate Streams with Fetch: read Fetch API integrated with Streams for more information.

Detecção de Recursos
--------------------

Fetch API support pode ser detectada na existência do escopo `Headers` (en-US), `Request`, `Response` ou `fetch()` (en-US) no `Window` ou `Worker` . Por exemplo, faça o seguinte teste no seu código:


```js
if (self.fetch) {
  // execute minha solicitação do fetch aqui
} else {
  // faça alguma coisa com XMLHttpRequest?
}
```

Fazendo as requisições Fetch
----------------------------

Uma requisição fetch é realizada para configuração. Temos um exemplo no seguinte código:


```js
var myImage = document.querySelector("img");

fetch("flowers.jpg")
  .then(function (response) {
    return response.blob();
  })
  .then(function (myBlob) {
    var objectURL = URL.createObjectURL(myBlob);
    myImage.src = objectURL;
  });
```


Aqui estamos procurando uma imagem e inserindo em um elemento `<img>`. O uso mais básico do`fetch()` acarreta em um argumento — a pasta do recurso que você deseja buscar — e retorna uma promessa contendo a resposta (a `Response` object).

Esta é apenas uma resposta HTTP, não a imagem em sí. Para extrairmos a imagem da resposta, nós usamos o método `blob()` (en-US) (definido no mixin do `Body`, que são implementados por ambos os objetos `Request` e `Response`.)

**Nota:** O Body mixin além disso possui métodos similares para extrair outros tipos de conteúdo do body; Veja a sessão Body para mais detalhes.

Um `objectURL` é criado na extração de `Blob`, que então é inserido no `img`.

Requisições Fetch são controladas pela directiva `connect-src` do Content Security Policy (en-US) ao invés da directiva do recurso retornado.

### Fornecendo opções de request

O método `fetch()` pode receber um segundo parametro opcional, que consiste em um objeto `init` que permite setar várias configurações:


```js
var myHeaders = new Headers();

var myInit = {
  method: "GET",
  headers: myHeaders,
  mode: "cors",
  cache: "default",
};

fetch("flowers.jpg", myInit)
  .then(function (response) {
    return response.blob();
  })
  .then(function (myBlob) {
    var objectURL = URL.createObjectURL(myBlob);
    myImage.src = objectURL;
  });
```


See `fetch()` (en-US) for the full options available, and more descriptions.

### Verificando se o fetch foi bem sucedido

Uma promise `fetch()` (en-US) será rejeitada com um `TypeError` quando um erro de rede é encontrado, embora isso geralmente signifique problemas de permissão ou similar — um 404 não constitui um erro de rede, por exemplo. Uma verificação precisa de um `fetch()` bem-sucedido incluiria a verificação de que a promessa foi resolvida e, em seguida, a verificação de que a propriedade `Response.ok` (en-US) tem o valor de `true`. O código seria parecido com o abaixo:


```js
fetch("flowers.jpg")
  .then(function (response) {
    if (response.ok) {
      response.blob().then(function (myBlob) {
        var objectURL = URL.createObjectURL(myBlob);
        myImage.src = objectURL;
      });
    } else {
      console.log("Network response was not ok.");
    }
  })
  .catch(function (error) {
    console.log(
      "There has been a problem with your fetch operation: " + error.message,
    );
  });
```

### Fornecendo seu próprio objeto de solicitação

Em vez de passar um caminho, para o recurso que você deseja solicitar, dentro da rquisição `fetch()`, você pode criar um objeto de solicitação usando o construtor `Request()`, e então passar a solicitação como um argumento do método `fetch()` :


```js
var myHeaders = new Headers();

var myInit = {
  method: "GET",
  headers: myHeaders,
  mode: "cors",
  cache: "default",
};

var myRequest = new Request("flowers.jpg", myInit);

fetch(myRequest)
  .then(function (response) {
    return response.blob();
  })
  .then(function (myBlob) {
    var objectURL = URL.createObjectURL(myBlob);
    myImage.src = objectURL;
  });
```


`Request()` aceita exatamente os mesmos parâmetros do método `fetch()`. Você pode até mesmo passar um objeto de solicitação existente para criar uma cópia dele:


```js
var anotherRequest = new Request(myRequest, myInit);
```


Isso é muito útil, pois os conteúdos de cada solicitação e resposta tem apenas um uso. Fazer uma cópia como essa permite que você use a solicitação / resposta novamente, variando as opções de inicialização, se desejar.

**Nota:** Também existe um método que cria uma cópia: `clone ()` (en-US). Isso tem uma semântica ligeiramente diferente do outro método de cópia: o primeiro dirá se o conteúdo, da solicitação anterior, já tiver sido lido (ou copiado), enquanto o segundo, `clone()` não.

Headers
-------

A interface `Headers` (en-US) permite que você crie seus proprios objetos headers por meio do construtor `Headers()` (en-US). Um objeto headers é um mapa multidimensional simples de nomes para o valor?


```js
var content = "Hello World";
var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
myHeaders.append("Content-Length", content.length.toString());
myHeaders.append("X-Custom-Header", "ProcessThisImmediately");
```


O mesmo pode ser feito passando um array de arrays ou um objeto literal para o construtor:


```js
myHeaders = new Headers({
  "Content-Type": "text/plain",
  "Content-Length": content.length.toString(),
  "X-Custom-Header": "ProcessThisImmediately",
});
```


O conteúdo pode ser consultado e recuperado:


```js
console.log(myHeaders.has("Content-Type")); // true
console.log(myHeaders.has("Set-Cookie")); // false
myHeaders.set("Content-Type", "text/html");
myHeaders.append("X-Custom-Header", "AnotherValue");

console.log(myHeaders.get("Content-Length")); // 11
console.log(myHeaders.getAll("X-Custom-Header")); // ["ProcessThisImmediately", "AnotherValue"]

myHeaders.delete("X-Custom-Header");
console.log(myHeaders.getAll("X-Custom-Header")); // [ ]
```


Some of these operations are only useful in `ServiceWorkers` (en-US), but they provide a much nicer API for manipulating headers.

All of the Headers methods throw a TypeError if a header name is used that is not a valid HTTP Header name. The mutation operations will throw a TypeError if there is an immutable guard (see below). Otherwise they fail silently. For example:


```js
var myResponse = Response.error();
try {
  myResponse.headers.set("Origin", "http://mybank.com");
} catch (e) {
  console.log("Cannot pretend to be a bank!");
}
```


A good use case for headers is checking whether the content type is correct before you process it further. For example:


```js
fetch(myRequest).then(function (response) {
  var contentType = response.headers.get("content-type");
  if (contentType && contentType.indexOf("application/json") !== -1) {
    return response.json().then(function (json) {
      // process your JSON further
    });
  } else {
    console.log("Oops, we haven't got JSON!");
  }
});
```

### Guard

Since headers can be sent in requests and received in responses, and have various limitations about what information can and should be mutable, headers objects have a guard property. This is not exposed to the Web, but it affects which mutation operations are allowed on the headers object.

Possible guard values are:

* `none`: default.
* `request`: guard for a headers object obtained from a request (`Request.headers` (en-US)).
* `request-no-cors`: guard for a headers object obtained from a request created with `Request.mode` (en-US) `no-cors`.
* `response`: guard for a Headers obtained from a response (`Response.headers` (en-US)).
* `immutable`: Mostly used for ServiceWorkers; renders a headers object read-only.

**Nota:** You may not append or set a `request` guarded Headers' `Content-Length` header. Similarly, inserting `Set-Cookie` into a response header is not allowed: ServiceWorkers are not allowed to set cookies via synthesized responses.

Response objects
----------------

As you have seen above, `Response` instances are returned when `fetch()` promises are resolved.

They can also be created programmatically via JavaScript, but this is only really useful in `ServiceWorkers` (en-US), when you are providing a custom response to a received request using a `respondWith()` (en-US) method:


```js
var myBody = new Blob();

addEventListener("fetch", function (event) {
  event.respondWith(
    new Response(myBody, {
      headers: { "Content-Type": "text/plain" },
    }),
  );
});
```


The `Response()` (en-US) constructor takes two optional arguments — a body for the response, and an init object (similar to the one that `Request()` accepts.)

The most common response properties you'll use are:

* `Response.status` (en-US) — An integer (default value 200) containing the response status code.
* `Response.statusText` (en-US) — A string (default value "OK"),which corresponds to the HTTP status code message.
* `Response.ok` (en-US) — seen in use above, this is a shorthand for checking that status is in the range 200-299 inclusive. This returns a `Boolean` (en-US).

**Nota:** The static method `error()` (en-US) simply returns an error response. Similarly, `redirect()` (en-US) returns a response resulting in
 a redirect to a specified URL. These are also only relevant to Service Workers.


Body
----

Both requests and responses may contain body data. A body is an instance of any of the following types.

* `ArrayBuffer`
* `ArrayBufferView` (en-US) (Uint8Array and friends)
* `Blob`/File
* string
* `URLSearchParams`
* `FormData`

The `Body` mixin defines the following methods to extract a body (implemented by both `Request` and `Response`). These all return a promise that is eventually resolved with the actual content.

* `arrayBuffer()` (en-US)
* `blob()` (en-US)
* `json()` (en-US)
* `text()` (en-US)
* `formData()` (en-US)

This makes usage of non-textual data much easier than it was with XHR.

Request bodies can be set by passing body parameters:


```js
var form = new FormData(document.getElementById("login-form"));
fetch("/login", {
  method: "POST",
  body: form,
});
```


Both request and response (and by extension the `fetch()` function), will try to intelligently determine the content type. A request will also automatically set a `Content-Type` header if none is set in the dictionary.

Especificações
--------------

{{Specifications}}Compatibilidade com navegadores
-------------------------------

{{Compat}}
* ServiceWorker API (en-US)
* HTTP access control (CORS) (en-US)
* HTTP
* Fetch polyfill
* Fetch examples on Github