JavaScript의 Fetch API와 유사한 XMLHttpRequest 래퍼 만들기
32352 단어 httprestjavascriptpromises
JS 표준 라이브러리의
fetch
API 함수를 사용할 때 매번 응답을 처리하려고 할 때마다 짜증이 납니다. 그래서 XMLHttpRequest 프로토타입에 대한 래퍼를 만들기로 결정했습니다. 그러면 응답을 더 쉽게 처리할 수 있고 Fetch API와 유사한 인터페이스를 갖게 됩니다(기본적으로 XMLHttpRequest 위에 있는 Fetch API의 대안).시작하기
XMLHttpRequest
는 특정 이벤트에 응답하고 응답에서 데이터를 제공하는 콜백 인터페이스를 지향하지만 HTTP 요청을 처리하기 위한 매우 간단한 API를 제공합니다.httpRequest
API 함수의 첫 번째 버전부터 시작하겠습니다.let httpRequest = function(method, url, { headers, body, options } = {}) {
method = method.toUpperCase()
let xhr = new XMLHttpRequest()
xhr.withCredentials = true;
xhr.open(method, url)
xhr.setRequestHeader("Content-Type", "application/json")
for (const key in headers) {
if (Object.hasOwnProperty.call(headers, key)) {
xhr.setRequestHeader(key, headers[key])
}
}
xhr.send(body)
return new Promise((resolve, reject) => {
xhr.onload = function() {
resolve(new HttpResponse(xhr))
}
xhr.onerror = function() {
reject(new HttpError(xhr))
}
})
}
여기에서 볼 수 있듯이 함수는 HTTP 메서드와 URL을 필수 매개변수로 받습니다. 작업에 필요한 기본 개체를 만든 후 요청을 보냅니다. 함수는
xhr
요청 객체에 대한 이벤트 콜백을 래핑하는 약속을 반환합니다. 특정 이벤트가 트리거되면 Promise 리졸버가 HttpResponse
및 HttpError
의 래핑된 값을 전송합니다.참고로 여기에서도
withCredentials
를 true
값으로 설정하여 CORS를 활성화했습니다. 이는 요청을 올바르게 실행하기 위해 서버에서도 활성화되어야 함을 의미합니다.이제
HttpResponse
프로토타입을 정의합니다.let HttpResponse = function(xhr) {
this.body = xhr.response
this.status = xhr.status
this.headers = xhr.getAllResponseHeaders().split("\r\n").reduce((result, current) => {
let [name, value] = current.split(': ');
result[name] = value;
return result;
})
this.parser = new DOMParser();
}
HttpResponse.prototype.json = function() {
return JSON.parse(this.body)
}
HttpResponse.prototype.getAsDOM = function() {
return this.parser.parseFromString(this.body, "text/html")
}
그것이 하는 유일한 일은
XMLHttpRequest
객체를 취하고 HTTP 응답을 처리할 때 가장 관심을 나타내는 특정 필드만 분해합니다: status
, body
및 headers
. parser
필드는 getAsDOM
메서드에서 사용하도록 정의됩니다. 그 특정 메서드는 text/html
콘텐츠를 구문 분석하고 이를 DOM 개체로 변환합니다.json
메서드는 매우 간단합니다. 본문에서 JSON을 구문 분석합니다.이제
HttpError
프로토타입을 살펴보겠습니다.let HttpError = function(xhr) {
this.body = xhr.response
this.status = xhr.status
this.headers = xhr.getAllResponseHeaders().split("\r\n").reduce((result, current) => {
let [name, value] = current.split(': ');
result[name] = value;
return result;
})
}
HttpError.prototype.toString = function() {
let json = JSON.parse(this.body)
return "["+ this.status + "] Error: " + json.error || json.errors.map(e => e.message).join(", ")
}
이것은
HttpResponse
프로토타입과 매우 유사하지만 JSON 오류 메시지에 대한 특정 규칙에 따라 오류 메시지를 래핑 해제하는 기능만 제공합니다.작동 방식을 확인해 보겠습니다.
let response = await httpRequest("GET", "https://api.your-domain.com/resource/1")
console.log(response.json())
그러면 응답의 JSON 본문이 반환됩니다.
업로드 진행 상황 추적
Fetch
API에 없는 또 다른 기능은 업로드 진행률 추적입니다. 입력 객체의 options
필드에 대한 콜백으로 추가할 수도 있습니다. 또한 요청 중에 오류가 발생했는지 추적하여 오류를 수신해야 합니다.두 번째 버전은 이러한 모든 변경 사항을 다룹니다.
let httpRequest = function(method, url, { headers, body, options } = {}) {
method = method.toUpperCase()
let xhr = new XMLHttpRequest()
xhr.withCredentials = true;
xhr.open(method, url, true)
xhr.setRequestHeader("Content-Type", "application/json")
for (const key in headers) {
if (Object.hasOwnProperty.call(headers, key)) {
xhr.setRequestHeader(key, headers[key])
}
}
if (options && options.hasOwnProperty("checkProgress")) {
xhr.upload.onprogress = options.checkProgress
}
xhr.send(body)
return new Promise((resolve, reject) => {
xhr.onload = function() {
resolve(new HttpResponse(xhr))
}
xhr.onerror = function() {
reject(new HttpError(xhr))
}
xhr.onabort = function() {
reject(new HttpError(xhr))
}
})
}
POST
요청을 찾는 방법을 살펴보겠습니다.let response = await httpRequest("POST", "https://api.your-domain.com/resource", {
body: JSON.stringify({"subject":"TEST!"}),
options: {
checkProgress: function(e) {
console.log('e:', e)
}
}
})
console.log(response.status)
console.log(response.json())
전체 구현을 한 번 더 살펴보겠습니다.
let HttpResponse = function(xhr) {
this.body = xhr.response
this.status = xhr.status
this.headers = xhr.getAllResponseHeaders().split("\r\n").reduce((result, current) => {
let [name, value] = current.split(': ');
result[name] = value;
return result;
})
this.parser = new DOMParser();
}
HttpResponse.prototype.json = function() {
return JSON.parse(this.body)
}
HttpResponse.prototype.getAsDOM = function() {
return this.parser.parseFromString(this.body, "text/html")
}
let HttpError = function(xhr) {
this.body = xhr.response
this.status = xhr.status
this.headers = xhr.getAllResponseHeaders().split("\r\n").reduce((result, current) => {
let [name, value] = current.split(': ');
result[name] = value;
return result;
})
}
HttpError.prototype.toString = function() {
let json = JSON.parse(this.body)
return "["+ this.status + "] Error: " + json.error || json.errors.join(", ")
}
let httpRequest = function(method, url, { headers, body, options } = {}) {
method = method.toUpperCase()
let xhr = new XMLHttpRequest()
xhr.withCredentials = true;
xhr.open(method, url, true)
xhr.setRequestHeader("Content-Type", "application/json")
for (const key in headers) {
if (Object.hasOwnProperty.call(headers, key)) {
xhr.setRequestHeader(key, headers[key])
}
}
if (options && options.hasOwnProperty("checkProgress")) {
xhr.upload.onprogress = options.checkProgress
}
xhr.send(body)
return new Promise((resolve, reject) => {
xhr.onload = function() {
resolve(new HttpResponse(xhr))
}
xhr.onerror = function() {
reject(new HttpError(xhr))
}
xhr.onabort = function() {
reject(new HttpError(xhr))
}
})
}
이 작은 코드 조각은
XMLHttpRequest
라이브러리를 활용하며 여전히 유사한 API를 가지고 있습니다. 물론 개선의 여지가 많으니 가능하시다면 댓글로 여러분의 아이디어를 공유해주세요.
Reference
이 문제에 관하여(JavaScript의 Fetch API와 유사한 XMLHttpRequest 래퍼 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/cristicurteanu/create-an-xmlhttprequest-wrapper-similar-with-fetch-api-in-javascript-3bpp텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)