fetch
Javascript에서는 fetch로 리소스를 비동기 요청을 할 수 있다. fetch
는 Promise
객체를 리턴한다.
비동기 처리란, 시간이 소요되는 작업이 완료될 때까지 계속 기다리지 않고 따로 처리하며, 일단 다른 코드들도 먼저 실행할 수 있게끔 하는 작업이다.
이처럼 비동기 처리로 얻은 데이터를 이용해야 하는 부분이 있을 경우, 비동기 처리가 모두 완료된 뒤에 변수 등 초기화 작업을 진행하는 등 비동기 작업의 흐름을 제어해야 한다.
fetch
는 아래 두 방법 모두와 같이 사용된다. 둘 다 동일한 결과를 리턴하지만, 어떻게 handle하는지가 다르다.
1) then
과 함께 사용되는 promise chaining
2) async/await
async/await
async
functions함수 앞의 async
가 의미하는 바는 해당 함수가 항상 💡Promise 객체를 리턴한다는 것이다. 예를 들어, 아래 함수는 resolved promise with the result of 1
를 리턴한다.
async function f() {
return 1;
}
f().then(alert); // 1
혹은 명시적으로 promise 객체를 리턴할 수 있다.
async function f() {
return Promise.resolve(1);
}
f().then(alert); // 1
따라서, async
는 함수가 non-promise인 것들을 감싼 promise 객체를 리턴함을 보장한다.
await
는 뭔데?// works only inside async functions
let value = await promise;
await
는 promise가 리턴될 때 까지 기다리게 해준다.
async function f() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("done!"), 1000)
});
let result = await promise; // wait until the promise resolves (*)
alert(result); // "done!"
}
f();
함수는 (*)
라인에서 기다리는데, promise가 settle 되면 다시 함수가 실행되고 result
에 리턴된 promise 가 할당된다.
즉!! await
는 promise가 settle될 때까지 함수 실행을 중단한 다음 리턴된 promise 로 다시 함수를 재개한다. javascript 엔진은 그 사이에 다른 스크립트 실행, 이벤트 처리 등 다른 작업을 수행할 수 있기 때문에 CPU 리소스를 소모하지 않는다.
위는 promise.then
를 사용하는 것보다 elegant한 syntax고 읽고 쓰기 좋은 코드라 할 수 있다.
async/await
사용한 Promise chaining Example.then
을 await
로 replace한다.async
를 붙여준다.async function showAvatar() {
// read our JSON
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
// read github user
let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
let githubUser = await githubResponse.json();
// show the avatar
let img = document.createElement('img');
img.src = githubUser.avatar_url;
img.className = "promise-avatar-example";
document.body.append(img);
// wait 3 seconds
await new Promise((resolve, reject) => setTimeout(resolve, 3000));
img.remove();
return githubUser;
}
showAvatar();
rejection의, throw 문이 있는 것처럼 error(에러)를 발생시킨다.
async function f() {
await Promise.reject(new Error("Whoops!"));
}
// or
async function f() {
throw new Error("Whoops!");
}
try...catch
문으로 일반 throw와 동일한 방식으로 해당 오류를 잡을 수 있다.
async function f() {
try {
let response = await fetch('http://no-such-url');
} catch(err) {
// catches errors both in fetch and response.json
alert(err); // TypeError: failed to fetch
}
}
f();
try...catch
가 없을 경우 .catch
를 추가하여 에러 처리 가능하다.
async/await
와 promise.then/catch
async/await
를 사용할 경우, .then
이 거의 필요하지 않다. 왜냐하면 await
가 waiting 역할을 담당해주기 때문이다. 그리고 .catch
대신 try...catch
문을 사용할 수 있는데, 항상은 아니지만 보통 더 편리하다.
하지만 코드의 top level, 즉 async
함수 바깥에서는 await
구문을 사용할 수 없기 때문에 에러(error) 처리나 final result 처리를 위해 .then/catch
구문을 사용하는게 normal practice다.
async/await
와 Promise.all
다수의 promise
를 wait해야 할 경우, Promise.all
로 wrap한 뒤 await
를 사용할 수 있다.
// wait for the array of results
let results = await Promise.all([
fetch(url1),
fetch(url2),
...
]);
출처