Promise em Requisições AJAX com JavaScript
Nos exemplos dos artigos anteriores, vimos que a criação de requisições Ajax utiliza chamadas repetitivas que diferem apenas em detalhes como a string de solicitação e as funções de processamento da resposta. Seria conveniente criar uma abstração comum para todas as ações relacionadas às requisições assíncronas Ajax e utilizá-la nas futuras solicitações ao servidor.
Para criar um nível adicional de abstração, é útil aplicar o objeto Promise
, que envolve a operação assíncrona em um único objeto. Esse objeto permite definir ações a serem executadas quando a operação é bem-sucedida ou falha.
Vamos encapsular uma requisição assíncrona em um objeto Promise
:
function get(url) {
return new Promise((succeed, fail) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.addEventListener("load", () => {
if (xhr.status >= 200 && xhr.status < 400) succeed(xhr.response);
else fail(new Error(`Request failed: ${xhr.statusText}`));
});
xhr.addEventListener("error", () => fail(new Error("Network error")));
xhr.send();
});
}
get("http://localhost:3000/hello")
.then((response) => console.log(response))
.catch((error) => console.error(error));
O método get
recebe como parâmetro o endereço do recurso no servidor e retorna um objeto Promise. O construtor Promise aceita uma função de callback que, por sua vez, recebe dois parâmetros: duas funções, uma para executar em caso de sucesso e outra em caso de falha na requisição.
Suponha que o servidor seja a seguinte aplicação simples em Node.js:
const http = require("http");
const fs = require("fs");
http
.createServer((request, response) => {
if (request.url == "/hello") {
response.end("XMLHttpRequest para Programício");
} else {
fs.readFile("index.html", (_error, data) => response.end(data));
}
})
.listen(3000, () => console.log("Servidor rodando em http://localhost:3000"));
Agora vamos chamar o método get
para realizar uma requisição ao servidor:
get("http://localhost:3000/hello")
.then((response) => console.log(response))
.catch((error) => console.error(error));
Para processar o resultado do objeto Promise
, utilizamos o método then()
, que aceita dois parâmetros: uma função chamada quando a requisição é bem-sucedida e outra chamada quando a requisição falha.
Neste caso, a função no primeiro then
recebe a resposta do servidor e a exibe no console.
Para tratar erros, podemos usar o método catch()
, que recebe uma função de tratamento de erros.
Da mesma forma, podemos enviar dados ao servidor usando Post:
function post(url, data) {
return new Promise((succeed, fail) => {
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.addEventListener("load", () => {
if (xhr.status >= 200 && xhr.status < 400) succeed(xhr.response);
else fail(new Error(`Request failed: ${xhr.statusText}`));
});
xhr.addEventListener("error", () => fail(new Error("Network error")));
xhr.send(data);
});
}
post("http://localhost:3000/user", "Tom")
.then((response) => console.log(response))
.catch((error) => console.error(error));
Neste caso, a string "Tom" será enviada para o endereço "http://localhost:3000/user"
.