Obtendo Dados da Resposta com a Fetch API em JavaScript
Todos os dados enviados pelo servidor estão disponíveis no objeto Response
através da propriedade body
, que representa um objeto ReadableStream
. No entanto, é muito mais fácil utilizar um dos métodos do objeto Response
. A interface Response
fornece os seguintes métodos:
arrayBuffer()
: retorna uma promise que obtém o conteúdo da resposta como um objetoArrayBuffer
.blob()
: retorna uma promise que obtém o conteúdo da resposta como um objetoBlob
.clone()
: retorna uma cópia do objetoResponse
atual.error()
: retorna um novo objetoResponse
associado a um erro de rede.formData()
: retorna uma promise que obtém o conteúdo da resposta como um objeto FormData.json()
: retorna uma promise que obtém o conteúdo da resposta como um objeto JSON.redirect()
: retorna um novo objetoResponse
com outro URL.text()
: retorna uma promise que obtém o conteúdo da resposta como uma string de texto.
Obtendo a Resposta como Texto
Para obter a resposta como texto, utilizamos o método text()
. Por exemplo, um servidor Node.js envia algum texto em resposta ao cliente:
const http = require("http");
const fs = require("fs");
http
.createServer(function (request, response) {
if (request.url == "/hello") {
response.end("Fetch para Programício");
} else {
fs.readFile("index.html", (error, data) => response.end(data));
}
})
.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Neste caso, ao acessar o endereço "/hello", o servidor envia ao cliente a string de texto "Fetch para Programício".
Na página index.html
, utilizamos o método text()
para obter essa string:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Programício</title>
</head>
<body>
<script>
fetch("/hello")
.then((response) => response.text())
.then((responseText) => console.log(responseText));
</script>
</body>
</html>
Para obter o texto enviado, chamamos o método response.text()
no objeto response, que retorna uma Promise
. Para acessar o texto da resposta, utilizamos um segundo método then()
onde, na função de callback, obtemos o texto da resposta:
then((responseText) => console.log(responseText));
Ou podemos usar async
/await
:
async function getText() {
// Obtém o objeto de resposta
const response = await fetch("/hello");
// Extrai o texto da resposta
const responseText = await response.text();
console.log(responseText);
}
getText();
Obtendo a Resposta como JSON
Suponha que o servidor envie um objeto JSON:
const http = require("http");
const fs = require("fs");
http
.createServer(function (request, response) {
if (request.url == "/user") {
const user = { name: "Tom", age: 37 };
response.end(JSON.stringify(user));
} else {
fs.readFile("index.html", (error, data) => response.end(data));
}
})
.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Neste caso, ao acessar o endereço "/user", o servidor envia o objeto user como um JSON.
Vamos obter esse objeto:
fetch("/user")
.then((response) => response.json())
.then((user) => console.log(user.name, " - ", user.age));
O método json()
retorna uma Promise
, então no segundo método then()
podemos obter o objeto JSON enviado e acessar suas propriedades:
.then(user => console.log(user.name, "-", user.age));
O mesmo exemplo utilizando async
/await
:
async function getUser() {
// Obtém o objeto de resposta
const response = await fetch("/user");
// Extrai o JSON da resposta
const user = await response.json();
console.log(user.name, "-", user.age);
}
getUser();
Enviando um Conjunto de Dados
De maneira semelhante, podemos receber um conjunto de objetos no formato JSON. Suponha que o servidor Node.js envie um array de objetos:
const http = require("http");
const fs = require("fs");
http
.createServer(function (request, response) {
if (request.url == "/users.json") {
const users = [
{ name: "Tom", age: 37 },
{ name: "Sam", age: 25 },
{ name: "Bob", age: 41 },
];
response.end(JSON.stringify(users));
} else {
fs.readFile("index.html", (error, data) => response.end(data));
}
})
.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Vamos obter esses dados na página web:
fetch("/users.json")
.then((response) => response.json())
.then((users) => users.forEach((user) => console.log(user.name, " - ", user.age)));
O método json()
retorna uma Promise
, então no segundo método then()
podemos obter o array de objetos JSON e acessar suas propriedades:
.then(users => users.forEach(user => console.log(user.name, " - ", user.age)));
O mesmo exemplo utilizando async
/await
:
async function getUsers() {
const response = await fetch("/users.json");
const users = await response.json();
users.forEach((user) => console.log(user.name, " - ", user.age));
}
getUsers();
Enviando um Arquivo JSON
Suponha que exista um arquivo users.json
no diretório do servidor com o seguinte conteúdo:
[
{ "name": "Tom", "age": 37 },
{ "name": "Sam", "age": 25 },
{ "name": "Bob", "age": 41 },
];
No caso de um servidor Node.js, poderíamos enviar esse arquivo da seguinte maneira:
const http = require("http");
const fs = require("fs");
http
.createServer(function (request, response) {
if (request.url == "/users.json") {
fs.readFile("users.json", (error, data) => response.end(data));
} else {
fs.readFile("index.html", (error, data) => response.end(data));
}
})
.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Dependendo da tecnologia específica do servidor, o envio de arquivos pode variar. Neste caso, assim como no envio do arquivo index.html
, lemos os dados do arquivo users.json
usando a função fs.readFile()
e enviamos na resposta.
No lado do cliente, o código seria o mesmo que no exemplo anterior:
fetch("/users.json")
.then((response) => response.json())
.then((users) => users.forEach((user) => console.log(user.name, " - ", user.age)));
Carregando Dados Binários
Com o método blob()
, é possível carregar dados binários. Vamos ilustrar isso com um exemplo de imagens. Suponha que exista um arquivo forest.jpg
no servidor.
O servidor Node.js pode enviar este arquivo ao acessar o endereço "forest.jpg":
const http = require("http");
const fs = require("fs");
http
.createServer(function (request, response) {
if (request.url == "/forest.jpg") {
fs.readFile("forest.jpg", (error, data) => response.end(data));
} else {
fs.readFile("index.html", (error, data) => response.end(data));
}
})
.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Na página web index.html
, definimos o seguinte código para acessar o servidor:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Programício</title>
</head>
<body>
<img />
<script>
const img = document.querySelector("img");
fetch("/forest.jpg")
.then((response) => response.blob())
.then((data) => (img.src = URL.createObjectURL(data)));
</script>
</body>
</html>
Para exibir a imagem na página web, definimos o elemento <img />
.
O método blob()
retorna uma Promise
que recebe os dados da resposta como um objeto Blob
. No segundo método then()
, obtemos esse objeto:
.then(data => img.src = URL.createObjectURL(data));
Aqui, precisamos definir o arquivo recebido como a fonte da imagem no elemento HTML <img />
. Para isso, chamamos a função URL.createObjectURL()
, passando o objeto Blob
. Esta função cria um URL para o arquivo carregado. Assim, após a execução da requisição, o elemento HTML <img />
exibirá a imagem carregada:
O mesmo exemplo utilizando async
/await
:
const img = document.querySelector("img");
async function getImage() {
const response = await fetch("/forest.jpg");
const imgBlob = await response.blob();
img.src = URL.createObjectURL(imgBlob);
}
getImage();
De maneira semelhante, podemos carregar e utilizar outros tipos de arquivos, como áudios e vídeos.