request, response 같은 http pipeline을 생성할 수 있게 해주는 javascript interace를 제공한다.
fecth는 jQuery.ajax()와 다른 점이 있다.
-
fetch로 부터 return 된 promise는 HTTP error status에 대한 거절이 없다. (404 or 500 에러일지라도.) 200~299 사이의 코드가 아닐경우 response의 ok property를 false로 바꾼다. 네트워크 실패나 request를 막는 요청일 경우를 제외하곤.
-
fetch는 cross-origin cookies를 보내진 않는다. credentials options을 주지 않는한. default credentials 정책은 same-origin이다.
가장 간단한 사용 방법
fetch('http://example.com/movies.json')
.then(response => response.json())
.then(data => console.log(data));
전체 옵션
// Example POST method implementation:
async function postData(url = '', data = {}) {
// Default options are marked with *
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
body: JSON.stringify(data) // body data type must match "Content-Type" header
});
return response.json(); // parses JSON response into native JavaScript objects
}
postData('https://example.com/answer', { answer: 42 })
.then(data => {
console.log(data); // JSON data parsed by `data.json()` call
});
mode : no-cors 옵션은 hedaers에 담을 수 있는 내용이 제한된다.
- Accept
- Accept-Language
- Content-Language
- Content-Type with a value of application/x-www-form-urlencoded, multipart/form-data, or text/plain
credentials를 포함한 request 요청
fetch('https://example.com', {
credentials: 'include'
});
- Access-Control-Allow-Origin 은 credentials: ‘include’에서 금지된다.
url이 same origin이면 send credentials을 하고 싶을 경우 credentials: ‘same-origin’을 사용한다.
credentials를 포함하고 싶지 않은 경우 credentials : ‘omit’ 을 사용한다.
JSON 데이터를 upload하는 경우
const data = { username: 'example' };
fetch('https://example.com/profile', {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
파일을 업로드하는 경우
을 사용하고 Formdata() fetch를 사용한다.
const formData = new FormData();
const fileField = document.querySelector('input[type="file"]');
formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);
fetch('https://example.com/profile/avatar', {
method: 'PUT',
body: formData
})
.then(response => response.json())
.then(result => {
console.log('Success:', result);
})
.catch(error => {
console.error('Error:', error);
});
파일을 여러개 업로드하는 경우
을 사용하고 Formdata() fetch를 사용한다.
const formData = new FormData();
const photos = document.querySelector('input[type="file"][multiple]');
formData.append('title', 'My Vegas Vacation');
for (let i = 0; i < photos.files.length; i++) {
formData.append('photos', photos.files[i]);
}
fetch('https://example.com/posts', {
method: 'POST',
body: formData,
})
.then(response => response.json())
.then(result => {
console.log('Success:', result);
})
.catch(error => {
console.error('Error:', error);
});
텍스트 파일을 한라인씩 프로세싱하는 경우
response로 부터 읽어드린 chunk가 line boundaries에서 꺠지지 않았거나 Unit8Arrays일때 (UTF-8에 fetch error는 handling하지 않는다고 가정)
async function* makeTextFileLineIterator(fileURL) {
const utf8Decoder = new TextDecoder('utf-8');
const response = await fetch(fileURL);
const reader = response.body.getReader();
let { value: chunk, done: readerDone } = await reader.read();
chunk = chunk ? utf8Decoder.decode(chunk) : '';
const re = /\n|\r|\r\n/gm;
let startIndex = 0;
let result;
for (;;) {
let result = re.exec(chunk);
if (!result) {
if (readerDone) {
break;
}
let remainder = chunk.substr(startIndex);
({ value: chunk, done: readerDone } = await reader.read());
chunk = remainder + (chunk ? utf8Decoder.decode(chunk) : '');
startIndex = re.lastIndex = 0;
continue;
}
yield chunk.substring(startIndex, result.index);
startIndex = re.lastIndex;
}
if (startIndex < chunk.length) {
// last line didn't end in a newline char
yield chunk.substr(startIndex);
}
}
async function run() {
for await (let line of makeTextFileLineIterator(urlOfFile)) {
processLine(line);
}
}
run();
fetch가 성공적인지에 대한 코드
fetch('flowers.jpg')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.blob();
})
.then(myBlob => {
myImage.src = URL.createObjectURL(myBlob);
})
.catch(error => {
console.error('There has been a problem with your fetch operation:', error);
});
network error이거나 CORS 문제일 경우 respose.ok가 false이다.
request object를 직접 생성하는 경우
const myHeaders = new Headers();
const myRequest = new Request('flowers.jpg', {
method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default',
});
fetch(myRequest)
.then(response => response.blob())
.then(myBlob => {
myImage.src = URL.createObjectURL(myBlob);
});
헤더
헤더 interface를 통해 직접 헤더를 만들 수 있다.
const content = 'Hello World';
const myHeaders = new Headers();
myHeaders.append('Content-Type', 'text/plain');
myHeaders.append('Content-Length', content.length.toString());
myHeaders.append('X-Custom-Header', 'ProcessThisImmediately');
const myHeaders = new Headers({
'Content-Type': 'text/plain',
'Content-Length': content.length.toString(),
'X-Custom-Header': 'ProcessThisImmediately'
});
헤더를 쓰기 좋은 예제 (프로세스 전에 content-type 이 맞는지 체크)
fetch(myRequest)
.then(response => {
const contentType = response.headers.get('content-type');
if (!contentType || !contentType.includes('application/json')) {
throw new TypeError("Oops, we haven't got JSON!");
}
return response.json();
})
.then(data => {
/* process your data further */
})
.catch(error => console.error(error));
Response Objects
- Response.status - 응답 코드
- Response.statusText - 응답 코드 메세지 (HTTP/2는 지원하지 않음)
- Response.ok - 200-299 응답에 있는 체크
respondWith로 받았을 때 사용 가능
const myBody = new Blob();
addEventListener('fetch', function(event) {
// ServiceWorker intercepting a fetch
event.respondWith(
new Response(myBody, {
headers: { 'Content-Type': 'text/plain' }
})
);
});
Body
types
- ArrayBuffer
- ArrayBufferView (Uint8Array and friends)
- Blob/File
- string
- URLSearchParams
- FormData
Request와 Response interface는 body를 추출하기 위해 함수를 공유한다.
- Request.arrayBuffer() / Response.arrayBuffer()
- Request.blob() / Response.blob()
- Request.formData() / Response.formData()
- Request.json() / Response.json()
- Request.text() / Response.text()
출처 https://developer.mozilla.org/ko/docs/Web/API/Fetch_API https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch