request(options)
설명
XHR(AJAX) 요청을 생성하고 Promise를 반환합니다.
m.request({
method: 'PUT',
url: '/api/v1/users/:id',
params: { id: 1 },
body: { name: 'test' },
}).then(function (result) {
console.log(result);
});
서명
promise = m.request(options)
인수 | 타입 | 필수 여부 | 설명 |
---|---|---|---|
options | Object | 예 | 요청에 사용할 옵션 객체입니다. |
options.method | String | 아니오 | 사용할 HTTP 메서드입니다. GET , POST , PUT , PATCH , DELETE , HEAD , OPTIONS 중 하나여야 합니다. 기본값은 GET 입니다. |
options.url | String | 예 | 요청을 보낼 경로 이름입니다. options.params 값을 사용하여 URL을 보간할 수 있습니다. |
options.params | Object | 아니오 | URL에 보간하거나 쿼리 문자열로 직렬화할 데이터입니다. |
options.body | Object | 아니오 | 요청 본문(body)으로 직렬화할 데이터입니다. |
options.async | Boolean | 아니오 | 요청을 비동기적으로 수행할지 여부입니다. |
options.user | String | 아니오 | HTTP 인증에 사용할 사용자 이름입니다. 기본값은 undefined 입니다. |
options.password | String | 아니오 | HTTP 인증에 사용할 비밀번호입니다. 기본값은 undefined 입니다. 이 옵션은 XMLHttpRequest 호환성을 위해 제공되지만, 네트워크를 통해 비밀번호를 평문으로 전송하므로 사용을 권장하지 않습니다. |
options.withCredentials | Boolean | 아니오 | 쿠키를 타사 도메인으로 보낼지 여부입니다. 기본값은 false 입니다. |
options.timeout | Number | 아니오 | 요청이 자동으로 중단되기까지 허용되는 시간(밀리초)입니다. 기본값은 undefined 입니다. |
options.responseType | String | 아니오 | 예상되는 응답 타입입니다. extract 가 정의된 경우 기본값은 "" 이고, 그렇지 않은 경우 "json" 입니다. responseType: "json" 인 경우 내부적으로 JSON.parse(responseText) 를 수행합니다. |
options.config | xhr = Function(xhr) | 아니오 | 기본 XMLHttpRequest 객체를 노출하여 저수준 설정을 하거나, 필요에 따라 객체를 교체(새 XHR 반환)할 수 있습니다. |
options.headers | Object | 아니오 | 요청을 보내기 전에 추가할 헤더입니다(options.config 직전에 적용됩니다). |
options.type | any = Function(any) | 아니오 | 응답의 각 객체에 적용될 생성자 함수입니다. |
options.serialize | string = Function(any) | 아니오 | body 에 적용될 직렬화 함수입니다. 기본값은 JSON.stringify 입니다. options.body 가 FormData 또는 URLSearchParams 의 인스턴스인 경우에는 기본값이 항등 함수 (예: function(value) {return value} )로 설정됩니다. |
options.deserialize | any = Function(any) | 아니오 | xhr.response 또는 정규화된 xhr.responseText 에 적용될 역직렬화 함수입니다. 기본값은 항등 함수입니다. extract 가 정의되어 있다면 deserialize 는 무시됩니다. |
options.extract | any = Function(xhr, options) | 아니오 | XMLHttpRequest 응답을 처리하는 방식을 지정하는 훅입니다. 응답 데이터 처리, 헤더 및 쿠키 읽기에 유용합니다. 기본적으로 이 훅은 options.deserialize(parsedResponse) 를 반환하는 함수이며, 서버 응답 상태 코드가 오류를 나타내거나 응답의 구문이 유효하지 않은 경우 예외를 발생시킵니다. 사용자 정의 extract 콜백을 제공하면 xhr 매개변수는 요청에 사용된 XMLHttpRequest 인스턴스를, options 는 m.request 호출에 전달된 객체를 가리킵니다. 또한 deserialize 는 무시되고, extract 콜백에서 반환된 값은 Promise가 resolve될 때 변경 없이 그대로 유지됩니다. |
options.background | Boolean | 아니오 | false 이면 요청 완료 시 마운트된 컴포넌트를 다시 렌더링하고, true 이면 다시 렌더링하지 않습니다. 기본값은 false 입니다. |
반환 | Promise | extract , deserialize 및 type 메서드를 통해 처리된 응답 데이터로 resolve되는 Promise를 반환합니다. 응답 상태 코드가 오류를 나타내는 경우 Promise는 reject되지만, extract 옵션을 설정하여 이를 방지할 수 있습니다. |
promise = m.request(url, options)
매개변수 | 타입 | 필수 여부 | 설명 |
---|---|---|---|
url | String | 예 | 요청을 보낼 경로 이름입니다. options.url 이 있는 경우 이 값을 덮어씁니다. |
options | Object | 아니오 | 전달할 요청 옵션입니다. |
반환 | Promise | extract , deserialize 및 type 메서드를 통해 처리된 응답 데이터로 resolve되는 Promise입니다. |
이 두 번째 형태는 기본적으로 m.request(Object.assign({url: url}, options))
와 동일하지만, 내부적으로 ES6 전역 Object.assign
을 사용하지 않습니다.
작동 방식
m.request
유틸리티는 XMLHttpRequest
의 래퍼로서, 원격 서버에 HTTP 요청을 보내 데이터를 저장하거나 검색할 수 있도록 합니다.
m.request({
method: 'GET',
url: '/api/v1/users',
}).then(function (users) {
console.log(users);
});
m.request
를 호출하면 Promise가 반환되고, Promise 체인이 완료되면 리렌더링이 트리거됩니다.
기본적으로 m.request
는 응답이 JSON 형식이라고 가정하고 JavaScript 객체 (또는 배열)로 파싱합니다.
HTTP 응답 상태 코드가 오류를 나타내는 경우 반환된 Promise는 reject됩니다. extract
콜백을 제공하면 Promise reject를 방지할 수 있습니다.
일반적인 사용법
다음은 m.request
를 사용하여 서버에서 데이터를 가져오는 컴포넌트의 예시입니다.
var Data = {
todos: {
list: [],
fetch: function () {
m.request({
method: 'GET',
url: '/api/v1/todos',
}).then(function (items) {
Data.todos.list = items;
});
},
},
};
var Todos = {
oninit: Data.todos.fetch,
view: function (vnode) {
return Data.todos.list.map(function (item) {
return m('div', item.title);
});
},
};
m.route(document.body, '/', {
'/': Todos,
});
서버 URL /api/items
로 요청을 보내면 JSON 형식의 객체 배열이 반환된다고 가정합니다.
m.route
가 호출되면 Todos
컴포넌트가 초기화됩니다. oninit
이 호출되고, 이는 m.request
를 호출합니다. 이를 통해 서버에서 객체 배열을 비동기적으로 가져옵니다. "비동기적으로"라는 의미는 JavaScript가 서버 응답을 기다리는 동안에도 다른 코드를 계속 실행할 수 있다는 뜻입니다. 이 경우 fetch
가 반환되고 컴포넌트가 원래 빈 배열을 Data.todos.list
로 사용하여 렌더링됩니다. 서버 요청이 완료되면 객체 배열 items
가 Data.todos.list
에 할당되고 컴포넌트가 다시 렌더링되며 각 todo
의 제목을 포함하는 <div>
목록이 생성됩니다.
오류 처리
file:
프로토콜이 아닌 요청이 2xx 또는 304 이외의 상태로 응답하면 오류와 함께 거부됩니다. 이 오류는 일반적인 Error 인스턴스이지만 몇 가지 특수한 속성이 있습니다.
error.message
는 원시 응답 텍스트로 설정됩니다.error.code
는 상태 코드 자체로 설정됩니다.error.response
는 일반 응답과 마찬가지로options.extract
및options.deserialize
를 사용하여 파싱된 응답으로 설정됩니다.
이는 오류 자체를 예상하고 처리할 수 있는 경우에 유용합니다. 세션이 만료되었는지 감지하려면 if (error.code === 401) return promptForAuth().then(retry)
를 수행할 수 있습니다. API의 스로틀링 메커니즘에 도달하여 "timeout": 1000
이 포함된 오류가 반환된 경우 setTimeout(retry, error.response.timeout)
를 수행할 수 있습니다.
로딩 아이콘 및 오류 메시지
다음은 로딩 표시기와 오류 메시지를 구현하기 위해 앞선 예제를 확장한 것입니다.
var Data = {
todos: {
list: null,
error: '',
fetch: function () {
m.request({
method: 'GET',
url: '/api/v1/todos',
})
.then(function (items) {
Data.todos.list = items;
})
.catch(function (e) {
Data.todos.error = e.message;
});
},
},
};
var Todos = {
oninit: Data.todos.fetch,
view: function (vnode) {
return Data.todos.error
? [m('.error', Data.todos.error)]
: Data.todos.list
? [
Data.todos.list.map(function (item) {
return m('div', item.title);
}),
]
: m('.loading-icon');
},
};
m.route(document.body, '/', {
'/': Todos,
});
이 예제와 이전 예제 사이에는 몇 가지 차이점이 있습니다. 여기서는 Data.todos.list
가 시작 시 null
입니다. 또한 오류 메시지를 보관하기 위한 추가 필드 error
가 있으며, Todos
컴포넌트의 뷰는 오류 메시지가 있는 경우 오류 메시지를 표시하거나 Data.todos.list
가 배열이 아닌 경우 로딩 아이콘을 표시하도록 수정되었습니다.
동적 URL
요청 URL에 보간을 사용할 수 있습니다.
m.request({
method: 'GET',
url: '/api/v1/users/:id',
params: { id: 123 },
}).then(function (user) {
console.log(user.id); // logs 123
});
위의 코드에서 :id
는 params
객체의 데이터로 채워지고 요청은 GET /api/v1/users/123
이 됩니다.
params
속성에 일치하는 데이터가 없으면 보간은 무시됩니다.
m.request({
method: 'GET',
url: '/api/v1/users/foo:bar',
params: { id: 123 },
});
위의 코드에서 요청은 GET /api/v1/users/foo:bar?id=123
이 됩니다.
요청 중단
때로는 요청을 중단하는 것이 좋습니다. 예를 들어 자동 완성기/타이프어헤드 위젯에서는 마지막 요청만 완료되도록 하는 것이 좋습니다. 자동 완성기는 일반적으로 사용자가 입력할 때마다 여러 요청을 발생시키는데, 네트워크의 특성상 HTTP 요청이 완료되는 순서가 예측 불가능하기 때문입니다. 만약 다른 요청이 마지막 요청보다 늦게 완료된다면, 위젯은 가장 최근의 요청 결과가 아닌 덜 관련성 높거나 잘못된 데이터를 표시할 수 있습니다.
m.request()
는 기본 XMLHttpRequest
객체를 options.config
매개변수를 통해 노출하므로 해당 객체에 대한 참조를 저장하고 필요할 때 abort
메서드를 호출할 수 있습니다.
var searchXHR = null;
function search() {
abortPreviousSearch();
m.request({
method: 'GET',
url: '/api/v1/users',
params: { search: query },
config: function (xhr) {
searchXHR = xhr;
},
});
}
function abortPreviousSearch() {
if (searchXHR !== null) searchXHR.abort();
searchXHR = null;
}
파일 업로드
파일을 업로드하려면 먼저 File
객체를 참조해야 합니다.
<input type="file">
요소에서 가져오는 것이 가장 간단한 방법입니다.
m.render(document.body, [m('input[type=file]', { onchange: upload })]);
function upload(e) {
var file = e.target.files[0];
}
위의 스니펫은 파일 입력을 렌더링합니다. 사용자가 파일을 선택하면 onchange
이벤트가 트리거되어 upload
함수를 호출합니다. e.target.files
는 File
객체 목록입니다.
다음으로 FormData
객체를 생성하여 multipart request를 구성해야 합니다. multipart request는 요청 본문에 파일 데이터를 담아 전송할 수 있도록 특별한 형식으로 만들어진 HTTP 요청입니다.
function upload(e) {
var file = e.target.files[0];
var body = new FormData();
body.append('myfile', file);
}
다음으로 m.request
를 호출하고 options.method
를 본문을 사용하는 HTTP 메서드 (예: POST
, PUT
, PATCH
)로 설정하고 FormData
객체를 options.body
로 사용해야 합니다.
function upload(e) {
var file = e.target.files[0];
var body = new FormData();
body.append('myfile', file);
m.request({
method: 'POST',
url: '/api/v1/upload',
body: body,
});
}
서버가 multipart 요청을 수락하도록 구성되었다고 가정하면 파일 정보는 myfile
키와 연결됩니다.
다중 파일 업로드
하나의 요청으로 여러 파일을 업로드할 수 있습니다. 이렇게 하면 일괄 업로드가 원자적으로 처리됩니다. 즉, 업로드 도중 오류가 발생하면 전체 파일이 처리되지 않으므로 일부 파일만 저장하는 것은 불가능합니다. 네트워크 문제 발생 시 최대한 많은 파일을 저장해야 한다면, 각 파일을 개별적인 요청으로 업로드하는 것을 고려해 보세요.
여러 파일을 업로드하려면 모든 파일을 FormData
객체에 추가하기만 하면 됩니다. 파일 입력을 사용하는 경우 입력에 multiple
속성을 추가하여 파일 목록을 가져올 수 있습니다.
m.render(document.body, [
m('input[type=file][multiple]', { onchange: upload }),
]);
function upload(e) {
var files = e.target.files;
var body = new FormData();
for (var i = 0; i < files.length; i++) {
body.append('file' + i, files[i]);
}
m.request({
method: 'POST',
url: '/api/v1/upload',
body: body,
});
}
진행률 추적
때로는 요청 처리 시간이 오래 걸리는 경우(예: 대용량 파일 업로드) 애플리케이션이 정상적으로 동작하고 있음을 사용자에게 알리기 위해 진행률 표시기를 보여주는 것이 좋습니다.
m.request()
는 기본 XMLHttpRequest
객체를 options.config
매개변수를 통해 노출하므로 XMLHttpRequest 객체에 이벤트 리스너를 연결할 수 있습니다.
var progress = 0;
m.mount(document.body, {
view: function () {
return [
m('input[type=file]', { onchange: upload }),
progress + '% completed',
];
},
});
function upload(e) {
var file = e.target.files[0];
var body = new FormData();
body.append('myfile', file);
m.request({
method: 'POST',
url: '/api/v1/upload',
body: body,
config: function (xhr) {
xhr.upload.addEventListener('progress', function (e) {
progress = e.loaded / e.total;
m.redraw(); // Mithril.js에게 데이터가 변경되었고 화면을 다시 그려야 함을 알립니다.
});
},
});
}
위의 예제에서는 파일 입력이 렌더링됩니다. 사용자가 파일을 선택하면 업로드가 시작되고 config
콜백에서 progress
이벤트 핸들러가 등록됩니다. 이 이벤트 핸들러는 XMLHttpRequest에서 진행률 업데이트가 있을 때마다 발생합니다. XMLHttpRequest의 진행률 이벤트는 Mithril.js의 가상 DOM 엔진에서 직접 처리되지 않으므로, 데이터가 변경되었고 화면을 다시 그려야 함을 Mithril.js에 알리기 위해 m.redraw()
를 호출해야 합니다.
응답을 타입으로 캐스팅
애플리케이션 아키텍처에 따라 요청의 응답 데이터를 특정 클래스나 타입으로 변환하는 것이 유용할 수 있습니다 (예: 날짜 필드를 일관되게 파싱하거나 헬퍼 메서드를 사용하기 위해).
생성자를 options.type
매개변수로 전달하면 Mithril.js는 HTTP 응답의 각 객체에 대해 인스턴스화를 수행합니다.
function User(data) {
this.name = data.firstName + ' ' + data.lastName;
}
m.request({
method: 'GET',
url: '/api/v1/users',
type: User,
}).then(function (users) {
console.log(users[0].name); // logs a name
});
위의 예제에서 /api/v1/users
가 객체 배열을 반환한다고 가정하면 User
생성자가 배열의 각 객체에 대해 인스턴스화됩니다 (즉, new User(data)
로 호출됨). 응답이 단일 객체를 반환하면 해당 객체가 body
인수로 사용됩니다.
비 JSON 응답
경우에 따라 서버 엔드포인트가 JSON 응답을 반환하지 않습니다. 예를 들어 HTML 파일, SVG 파일 또는 CSV 파일을 요청할 수 있습니다. Mithril.js는 기본적으로 응답을 JSON 형식으로 간주하고 파싱하려고 시도합니다. 이러한 동작을 변경하려면 사용자 정의 options.deserialize
함수를 정의해야 합니다.
m.request({
method: 'GET',
url: '/files/icon.svg',
deserialize: function (value) {
return value;
},
}).then(function (svg) {
m.render(document.body, m.trust(svg));
});
위의 예제에서 요청은 SVG 파일을 검색하고 파싱하기 위해 아무 작업도 수행하지 않으며 (deserialize
는 값을 있는 그대로 반환하기 때문에) SVG 문자열을 신뢰할 수 있는 HTML로 렌더링합니다.
물론 deserialize
함수는 더 정교할 수 있습니다.
m.request({
method: 'GET',
url: '/files/data.csv',
deserialize: parseCSV,
}).then(function (data) {
console.log(data);
});
function parseCSV(data) {
// 예제를 간단하게 유지하기 위한 순진한 구현
return data.split('\n').map(function (row) {
return row.split(',');
});
}
위의 parseCSV 함수가 적절한 CSV 파서가 처리할 많은 경우를 처리하지 않는다는 사실을 무시하면 위의 코드는 배열의 배열을 기록합니다.
사용자 정의 헤더도 이와 관련하여 도움이 될 수 있습니다. 예를 들어 SVG를 요청하는 경우 콘텐츠 타입을 적절하게 설정하는 것이 좋습니다. 기본 JSON 요청 타입을 덮어쓰려면 options.headers
를 요청 헤더 이름 및 값에 해당하는 키-값 쌍의 객체로 설정합니다.
m.request({
method: 'GET',
url: '/files/image.svg',
headers: {
'Content-Type': 'image/svg+xml; charset=utf-8',
Accept: 'image/svg, text/*',
},
deserialize: function (value) {
return value;
},
});
응답 정보 가져오기
기본적으로 Mithril.js는 xhr.responseText
를 JSON으로 파싱한 후 파싱된 객체를 반환합니다. 서버 응답에 대한 더 자세한 정보를 확인하고 직접 처리해야 할 경우, 사용자 정의 options.extract
함수를 사용하여 이를 수행할 수 있습니다.
m.request({
method: 'GET',
url: '/api/v1/users',
extract: function (xhr) {
return { status: xhr.status, body: xhr.responseText };
},
}).then(function (response) {
console.log(response.status, response.body);
});
options.extract
함수의 인자는 XMLHttpRequest 객체이며, 요청 작업이 완료된 시점이지만 Promise 체인으로 전달되기 전입니다. 따라서 extract 함수 내에서 예외가 발생하면 Promise는 reject될 수 있습니다.
IP 주소로 요청 보내기
URL에서 파라미터를 인식하는 방식이 단순하기 때문에 IPv6 주소의 일부가 경로 파라미터 보간으로 잘못 인식될 수 있습니다. 경로 파라미터가 제대로 보간되려면 구분자가 필요한데, IPv6 주소에서는 이러한 구분자가 없어 오류가 발생합니다.
// This doesn't work
m.request('http://[2001:db8::990a:cd27:4d9e:79]:8080/some/path', {
// ...
});
이 문제를 해결하려면 IPv6 주소 + 포트 쌍을 매개변수로 전달해야 합니다.
m.request('http://:host/some/path', {
params: { host: '[2001:db8::990a:cd27:4d9e:79]:8080' },
// ...
});
이는 IPv4 주소의 문제가 아니며 정상적으로 사용할 수 있습니다.
// This will work as you expect
m.request('http://192.0.2.15:8080/some/path', {
// ...
});
HTML 대신 JSON을 사용하는 이유
많은 서버 측 프레임워크는 HTML을 제공하기 전에 (페이지 로드 시 또는 AJAX를 통해) 데이터베이스의 데이터를 템플릿에 삽입하는 뷰 엔진을 제공하고, jQuery를 사용하여 사용자 인터랙션을 처리합니다.
반면, Mithril.js는 일반적으로 템플릿과 데이터를 별도로 다운로드한 다음 JavaScript를 사용하여 브라우저에서 결합하는 싱글 페이지 애플리케이션(SPA) 개발에 적합한 프레임워크입니다.
브라우저에서 템플릿 작업을 처리하면 서버 자원을 절약하여 운영 비용을 줄일 수 있습니다. 템플릿과 데이터를 분리함으로써 템플릿 코드를 더욱 효율적으로 캐싱하고, 데스크톱, 모바일 등 다양한 유형의 클라이언트에서 코드 재사용성을 높일 수 있습니다. 또한 Mithril.js는 유지 모드 UI 개발 패러다임을 지원하여 복잡한 사용자 인터랙션의 개발 및 유지보수를 간소화합니다.
기본적으로 m.request
는 응답 데이터가 JSON 형식일 것으로 예상합니다. 일반적인 Mithril.js 애플리케이션에서 해당 JSON 데이터는 일반적으로 뷰에서 사용됩니다.
Mithril을 사용하여 서버에서 생성된 동적 HTML을 렌더링하는 것은 권장되지 않습니다. 서버 측 템플릿 시스템을 사용하는 기존 애플리케이션을 재구축하려는 경우, 먼저 이 작업이 실현 가능한지 신중하게 판단해야 합니다. 서버 중심 아키텍처에서 클라이언트 중심 아키텍처로 마이그레이션하는 것은 상당한 노력이 필요한 작업이며, 템플릿에 포함된 로직을 데이터 서비스 레이어로 리팩토링하는 과정(및 그에 따른 테스트)을 포함합니다.
데이터 서비스는 애플리케이션의 특성에 따라 다양한 방식으로 구성될 수 있습니다. RESTful 아키텍처는 API 제공업체에서 널리 사용되며, 트랜잭션 기반 워크플로우가 많은 경우에는 서비스 지향 아키텍처가 필요할 수 있습니다.
fetch
대신 XHR
을 사용하는 이유
fetch()
는 XMLHttpRequest
와 유사하게 서버에서 리소스를 가져오는 최신 Web API입니다.
Mithril.js의 m.request
가 fetch()
대신 XMLHttpRequest
를 사용하는 이유는 다음과 같습니다.
fetch
는 아직 완전히 표준화되지 않았으며 사양 변경이 있을 수 있습니다.XMLHttpRequest
호출은 resolve되기 전에 중단될 수 있습니다 (예: 즉석 검색 UI에서 경합 상태를 방지하기 위해).XMLHttpRequest
는 장기 실행 요청 (예: 파일 업로드)에 대한 진행률 리스너를 위한 훅을 제공합니다.XMLHttpRequest
는 모든 브라우저에서 지원되지만fetch()
는 Internet Explorer 및 이전 Android (5.0 Lollipop 이전)에서 지원되지 않습니다.
Mithril.js의 XHR 모듈은 크기가 훨씬 작음에도 불구하고 Mithril.js의 자동 리드로우(redraw) 하위 시스템과의 완벽한 통합은 물론, URL 보간 및 쿼리 문자열 직렬화와 같이 구현하기 쉽지 않은 많은 중요한 기능들을 지원합니다. 반면 fetch
폴리필은 이러한 기능들을 지원하지 않으며, 동일한 수준의 기능을 구현하려면 추가적인 라이브러리와 보일러플레이트 코드가 필요합니다.
또한 Mithril.js의 XHR 모듈은 JSON 기반 엔드포인트에 최적화되어 있어 가장 일반적인 사용 사례를 간결하게 처리할 수 있습니다 (예: m.request(url)
). 반면 fetch
를 사용할 경우 응답 데이터를 JSON으로 파싱하는 명시적인 단계를 추가해야 합니다 (fetch(url).then(function(response) {return response.json()})
).
fetch()
API는 몇 가지 드문 경우에 XMLHttpRequest
보다 몇 가지 기술적 이점이 있습니다.
- 스트리밍 API (리액티브 프로그래밍이 아닌 "비디오 스트리밍"의 의미)를 제공하여 매우 큰 응답을 처리할 때 지연 시간과 메모리 사용량을 줄일 수 있습니다 (코드 복잡성이 증가하는 단점은 있습니다).
- Service Worker API에 통합되어 네트워크 요청이 발생하는 방식과 시기에 대한 추가 제어 계층을 제공합니다. 이 API는 푸시 알림 및 백그라운드 동기화 기능에 대한 액세스도 허용합니다.
일반적인 상황에서는 스트리밍이 뚜렷한 성능 향상을 가져다주지 않습니다. 애초에 수 메가바이트에 달하는 데이터를 다운로드하는 것 자체가 권장되지 않기 때문입니다. 또한 작은 버퍼를 반복적으로 재사용하여 얻는 메모리 절약 효과는 과도한 브라우저 리페인팅을 유발할 경우 상쇄되거나 무효화될 수 있습니다. 따라서 m.request
대신 fetch()
스트리밍을 선택하는 것은 극도로 리소스 사용량이 많은 애플리케이션에만 권장됩니다.
안티 패턴 피하기
Promise
는 응답 데이터가 아닙니다.
m.request
메서드는 응답 데이터 자체가 아닌 Promise
를 반환합니다. HTTP 요청은 네트워크 지연 등으로 인해 완료하는 데 시간이 오래 걸릴 수 있습니다. JavaScript가 요청 완료를 기다리는 동안에는 애플리케이션이 멈추게 되므로, 응답 데이터를 즉시 반환할 수 없습니다.
// AVOID
var users = m.request('/api/v1/users');
console.log('list of users:', users);
// `users`는 사용자 목록이 아닌 Promise 객체입니다.
// PREFER
m.request('/api/v1/users').then(function (users) {
console.log('list of users:', users);
});