Objeto XMLHttpRequest - JavaScript
O código JavaScript pode interagir com recursos na internet, como sites ou serviços web, basicamente, com servidores. Para a interação do código JavaScript com o servidor, é geralmente utilizada a tecnologia AJAX. Ajax é uma tecnologia para enviar requisições ao servidor a partir do código cliente JavaScript sem recarregar a página. O termo significa Asynchronous JavaScript And XML. Inicialmente, o AJAX foi concebido para interações assíncronas entre cliente e servidor usando dados em formato XML, embora atualmente o formato JSON tenha substituído amplamente o XML.
Um dos métodos para enviar requisições Ajax é utilizando o objeto XMLHttpRequest
const xhr = new XMLHttpRequest();
Para configurar e enviar requisições Ajax, o objeto XMLHttpRequest
: interrompe a requisiçãoabort()
: retorna todos os cabeçalhos da resposta HTTP como uma stringgetAllResponseHeaders()
: retorna o valor do cabeçalho especificadogetResponseHeader(header)
: inicializa a requisição Ajaxopen(method, url[, async[, user[, password]]])
Essa função aceita cinco parâmetros, dos quais os dois primeiros são obrigatórios:
: tipo de requisição ("GET", "POST", "PUT", "DELETE", etc.)method
: endereço do recurso para o qual a requisição é enviadaurl
: valor booleano que indica se a requisição será assíncrona. Se for true (padrão), a requisição é assíncrona. Os modos síncrono e assíncrono diferem em que, no modo síncrono, enquanto a requisição não for completada, o restante do código JavaScript não pode ser executado. No modo assíncrono, outras partes do código JavaScript podem ser executadas em paralelo à execução da requisição. Na maioria dos casos, é utilizado o modo assíncrono.async
: nome do usuário para autenticação no servidor (padrão éuser
)null
: senha do usuário para autenticação no servidor (padrão épassword
)null
: sobrescreve o tipo MIME retornado pelo servidoroverrideMimeType(mime)
: envia a requisição. Com o parâmetro opcionalsend(data)
, é possível enviar dados para o servidor. Se nenhum valor for passado, seu padrão édata
.null
: define o valor do cabeçalho que será enviado na requisição.setRequestHeader(header, value)
Propriedades do XMLHttpRequest
Além dos métodos, o objeto XMLHttpRequest
: retorna a resposta do servidor. A resposta pode ser umresponse
,ArrayBuffer
,Blob
, objetoDocument
,JSON
oustring
(se a requisição ainda não foi concluída ou falhou).null
: retorna o tipo de resposta. Os possíveis tipos são:responseType
: string vazia""
: resposta como ArrayBuffer com dados bináriosarraybuffer
: resposta como Blob com dados bináriosblob
: resposta como Document (HTML/XML)document
: resposta em formato JSONjson
: resposta como textotext
: retorna a resposta do servidor como string ouresponseText
(se a requisição ainda não foi concluída ou falhou)null
: retorna a resposta do servidor como objetoresponseXML
(HTML/XML) se a resposta estiver em formato XML/HTMLDocument
: mantém o estado da requisição como um número:readyState
: objeto0
criado, mas o métodoXMLHttpRequest
ainda não foi chamadoopen()
: método1
foi chamado, mas a requisição ainda não foi enviadaopen()
: requisição enviada, cabeçalhos e status da resposta recebidos e prontos para uso2
: resposta sendo recebida do servidor3
: requisição concluída (mesmo que ocorra um erro, como código 404)4
Verificando essa propriedade, é possível entender em que estágio a requisição está.
: contém o código de status da resposta HTTP do servidor. Com o código de status, é possível determinar o sucesso da requisição ou identificar erros. Por exemplo, código 200 indica sucesso. Código 403 indica necessidade de autenticação, e 404 informa que o recurso não foi encontrado.status
: retorna o texto do status da resposta, por exemplo, "200 OK"statusText
: define o tempo limite em milissegundos para a execução da requisição. Se esse tempo for excedido, a requisição é interrompidatimeout
: determina se as credenciais, como cookies, devem ser incluídas na requisiçãowithCredentials
Eventos e Manipuladores de Eventos do XMLHttpRequest
Para acompanhar o estado da requisição, podemos utilizar eventos do XMLHttpRequest
: ocorre após a interrupção da requisição. O manipulador é definido pela propriedadeabort
.onabort
: ocorre durante a execução da requisição. O manipulador é definido pela propriedadeprogress
.onprogress
: ocorre após a conclusão da requisição. O manipulador é definido pela propriedadeload
.onload
: ocorre após a conclusão bem-sucedida da requisição. O manipulador é definido pela propriedadeloadend
.onloadend
: ocorre quando há um erro. O manipulador é definido pela propriedadeerror
.onerror
: ocorre após o início da requisição. O manipulador é definido pela propriedadeloadstart
.onloadstart
: ocorre se a requisição for interrompida devido ao tempo limite. O manipulador é definido pela propriedadetimeout
.ontimeout
: ocorre sempre que o valor da propriedadereadystatechange
muda. O manipulador é definido pela propriedadereadyState
.onreadystatechange
Para definir os manipuladores de eventos, podemos usar as seguintes propriedades do XMLHttpRequest
: chamado quando a requisição é interrompida pelo método abort().onabort
: chamado quando ocorre um erro.onerror
: chamado quando a requisição é concluída com sucesso e a resposta está disponível.onload
: chamado após a conclusão da requisição.onloadend
: chamado após o início da requisição.onloadstart
: chamado durante a execução da requisição.onprogress
: chamado quando o estado da requisição muda.onreadystatechange
: chamado se a requisição for interrompida devido ao limite do tempo.ontimeout
: usado para acompanhar o status durante o upload de dados.upload
Processo de Execução da Requisição Ajax
De modo geral, o processo de execução de uma requisição Ajax com o XMLHttpRequest
Cria-se um objeto XMLHttpRequest:
const request = new XMLHttpRequest();
Define-se um manipulador de eventos para o carregamento (por exemplo, através da propriedade
), que será chamado após a conclusão da requisição HTTP:onload
request.onload = (event) => { console.log("requisição concluída"); }
Inicia-se a requisição HTTP com o método
. Este método recebe o método HTTP a ser usado (por exemplo, GET ou POST), o URL para o qual a requisição será enviada e, se necessário, outros argumentos opcionais:open()
request.open("GET", "http://localhost/hello");
Se necessário, configura-se adicionalmente a requisição HTTP. Por exemplo, com o método
, é possível definir cabeçalhos a serem enviados com a requisição. É importante fazer essa configuração após a chamada do métodosetRequestHeader()
, mas antes da chamada do métodoopen()
:send()
request.setRequestHeader("Accept", "text/plain"); // define o cabeçalho para aceitar dados em texto plano
Envia-se a requisição HTTP com a chamada do método
. Se desejado, é possível passar dados para serem enviados ao servidor:send()
request.send();
A seguir, vamos ver um exemplo simples de como realizar uma requisição ao servidor utilizando XMLHttpRequest:
Definindo o Recurso no Servidor
Como o Ajax envolve a interação entre cliente e servidor, precisamos de um recurso de rede ao qual faremos solicitações. Para simular um recurso de rede, usaremos um servidor web local. O servidor web pode ser qualquer um, mas neste caso, utilizaremos a opção mais simples: Node.js. Esta tecnologia é bastante simples, disponível para todos os sistemas operacionais principais e permite usar JavaScript para criar aplicações. No entanto, antes de criar a aplicação, é necessário instalar o Node.js. Não é necessário ter conhecimentos prévios de Node.js, pois todo o código utilizado será explicado detalhadamente. Contudo, ao invés do Node.js, poderia ser utilizada qualquer outra tecnologia de servidor, como PHP, ASP.NET, Python, entre outras, ou um servidor web específico como Apache ou IIS.
Primeiramente, crie uma pasta no disco rígido para os arquivos do servidor web. Por exemplo, no meu caso, a pasta é C:\app. Em seguida, dentro dessa pasta, crie um arquivo para o servidor. Vamos chamá-lo de server.js, com o seguinte código:
const http = require("http");
const fs = require("fs");
http.createServer(function(request, response) {
if (request.url == "/hello") {
response.end("Hello Programício");
} else {
fs.readFile("index.html", (error, data) => response.end(data));
}
}).listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Este é o servidor mais básico, suficiente para a nossa tarefa. Vamos passar rapidamente pelo código:
Primeiro, conectamos os pacotes com a funcionalidade que vamos usar:
const http = require("http"); // para processar solicitações recebidas
const fs = require("fs"); // para ler o arquivo index.html do disco rígido
Para criar o servidor, usamos a função http.createServer()
request
response
Na função de callback, usamos a propriedade request.url
response.end()
if (request.url == "/hello") {
response.end("Hello Programício");
}
Se a solicitação for para outro recurso, enviamos o arquivo index.html
else {
fs.readFile("index.html", (error, data) => response.end(data));
}
Para ler arquivos, usamos a função embutida fs.readFile()
index.html
server.js
data
response.end(data)
Por fim, com a função listen(),
http://localhost:3000/
Executando a Requisição Ajax
Agora, na pasta do servidor, definiremos um arquivo simples chamado index.html com o seguinte conteúdo:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Programício</title>
</head>
<body>
<script>
const xhr = new XMLHttpRequest();
// Requisição GET para o recurso /hello
xhr.open("GET", "/hello");
// Manipulador de resposta do servidor
xhr.onload = () => {
if (xhr.status == 200) { // se o código de resposta for 200
console.log(xhr.responseText); // exibimos a resposta no console do navegador
} else { // caso contrário, exibimos o texto do status
console.log("Resposta do servidor: ", xhr.statusText);
}
};
xhr.send(); // enviamos a requisição
</script>
</body>
</html>
No método xhr.open()
xhr.open("GET", "/hello");
Para acompanhar a conclusão da requisição, definimos um manipulador para o evento load
xhr.onload
xhr.onload = () => {
if (xhr.status == 200) { // se o código de resposta for 200
console.log(xhr.responseText); // exibimos a resposta no console do navegador
} else { // caso contrário, exibimos o texto do status
console.log("Resposta do servidor: ", xhr.statusText);
}
};
Neste caso, o manipulador de eventos é uma expressão lambda. Quando a requisição é concluída, este manipulador é executado. Se a requisição foi processada com sucesso, o servidor envia o código de status 200 por padrão. Como lembramos do código do servidor, ao acessar o endereço "/hello", o servidor envia ao cliente uma string. Para obter essa string, acessamos a propriedade xhr.responseText
xhr.statusText
Finalmente, enviamos a requisição:
xhr.send(); // enviamos a requisição
Dessa forma, ao carregar esta página web, uma requisição Ajax será feita ao servidor.
Agora, na linha de comando, navegue até a pasta do servidor usando o comando cd
node server.js
C:\app>node server.js Servidor iniciado em http://localhost:3000
Após iniciar o servidor, podemos acessar o endereço http://localhost:3000
Ao acessar o recurso "/hello", o servidor enviará a string "Hello Programício", que poderemos receber na página web.
No exemplo acima, usamos um caminho relativo, mas também poderíamos usar um caminho absoluto especificando o protocolo, endereço do servidor e porta:
xhr.open("GET", "http://localhost:3000/hello");
Em vez de usar o evento load
readystatechange
XMLHttpRequest
readyState
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Programício</title>
</head>
<body>
<script>
const xhr = new XMLHttpRequest();
// Requisição GET para o recurso /hello
xhr.open("GET", "/hello");
// Manipulador de resposta do servidor
xhr.onreadystatechange = () => {
if (xhr.readyState == 4) { // se a requisição estiver concluída
if (xhr.status == 200) { // se o código de resposta for 200
console.log(xhr.responseText); // exibimos a resposta no console do navegador
} else { // caso contrário, exibimos o texto do status
console.log("Resposta do servidor: ", xhr.statusText);
}
}
};
xhr.send(); // enviamos a requisição
</script>
</body>
</html>
Aqui, no manipulador de eventos, primeiro verificamos o estado da requisição. Se o código de estado for 4, processamos a resposta do servidor. A lógica restante é a mesma do exemplo anterior.