비동기 함수의 실행 순서
console.log('Strart');
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.text())
.then((result) => {console.log(result);});
console.log('End');
위 코드의 실행 결과는 아래와 같다.
Start
End
result객체
fetch가 비동기동작을 하기 때문.
fetch('https://jsonplaceholder.typicode.com/users')
1. request를 보내면 어떤 객체(Promise 객체)를 리턴한다.
.then((response) => response.text())
2. 그 객체의 then메서드를 사용해서, 콜백을 등록한다.
콜백은 서버로부터 리스폰스를 받았을 때 실행된다.
.then((result) => {console.log(result);});
3. 두번째 then메서드도 콜백을 등록한다.
두번째 콜백은 첫번째 콜백이 실행된 이후에 실행된다.
첫번째 콜백의 리턴값을 파라미터로 넘겨받는다.
두개의 then메서드는 콜백을 바로 실행하는 것이 아니라 콜백을 등록만 한것이다.
4. then메서드가 콜백을 등록하고 나면, 콘솔에 'End'가 찍힌다.
5. 이후 등록된 콜백이 실행되며 결과가 출력된다.
간단하게는 아래와 같다.
- console.log('Start');
- fetch 함수(리퀘스트 보내기 및 콜백 등록)
- console.log('End');
- 리스폰스가 오면 2. 에서 then 메소드로 등록해뒀던 콜백 실행
비동기 실행 함수들
1. setTimeout
특정함수의 실행을 원하는 시간만큼 뒤로 미루기 위해 사용하는 함수이다.
console.log('a');
setTimeout(() => { console.log('b'); }, 2000);
console.log('c');
- setTimeout함수로 인해 console.log('b')로직을 갖는 함수가 2000밀리시컨(2초)뒤에 실행된다.
- fetch함수는 콜백이 실행되는 조건이’ 리스폰스가 도착했을 때 '였고,
- setTimeout함수는 '설정한 밀리세컨즈만큼의 시간이 경과했을 때' 이다.
2. setInterval
특정 콜백을 일정한 시간 간격으로 실행하도록 등록하는 함수이다.
console.log('a');
setInterval(() => { console.log('b'); }, 2000);
console.log('c');
- 2초 간격으로 console.log('b')로직을 가지는 함수가 반복실행된다.
3. addEventListener
DOM객체의 메소드이다.
btn.addEventListener('click', function (e) {
console.log('Hello Codeit!');
});
- 예시코드의 실행조건은 '클릭 이벤트가 발생했을 때' 이다.
Promise 객체
- 어떤 작업에 대한 상태 정보를 가지고 있는 객체이다.
- promise객체는 then 메서드를 가지고있고, then메서드를 통해 콜백을 등록할 수 있다.
promise객체가 가질 수 있는 상태
- 작업이 진행중이라는 pending
- 작업이 성공적으로 완료되었다는 fulfilled
- 작업이 실패했다는 rejected 상태
- 만약 promise객체가 fulfilled상태가되면 promise는 작업의 성공결과를 가진다.
- 만약 promise객체가 rejected상태가 되면 작업 실패 이유에대한 정보를 가지게된다.
- then메서드는 promise객체의 상태가 pending -> fulfilled 상태가 되었을 때 실행할 콜백을 등록하는 메서드이다.
- 서버로부터 response가 오면 promise객체의 상태가 fulfilled가 되고 등록해둔 콜백이 실행된다.
- 그리고 작업성공결과가 then메서드의 파라미터로 넘겨진다.
promise chaining
- then메서드 뒤에는 계속해서 then을 붙일 수 있다.
- 연속적으로 then을 붙이는 것을 promise chanining이라고부른다.
- porimise객체들을 계속해서 연결해 붙인것을 의미한다.
then메서드도 promise객체를 리턴하기때문에 가능하다.
promise chaining이 필요한 경우
// 수정 전
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.text())
.then((result) => {
const users = JSON.parse(result);
const { id } = users[0];
fetch(`https://jsonplaceholder.typicode.com/posts?userID=${id}`)
.then((response) => response.text())
.then((post) => {
console.log(posts);
});
});
// 수정 후
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.text())
.then((result) => {
const users = JSON.parse(result);
const { id } = users[0];
return fetch(`https://jsonplaceholder.typicode.com/posts?userID=${id}`);
})
.then((response) => response.text())
.then((post) => {
console.log(posts);
});
- promise chaining은 promise를 리턴하는 코드를 순차적으로 처리하고자 할 때 적용한다.
- 비동기 작업을 순차적으로 처리하기 위해서 사용하는 것이다.
- 순차적으로 처리해야하는 비동기 작업이 많을 경우에도, then메서드를 이어작성함으로써 깔끔한 코드를 유지할 수 있다.
then메서드가 리턴하는 값
1. promise객체를 리턴하는 경우
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.text())
);
- text()함수는 promise객체를 리턴한다.
- then메서드로 등록된 콜백(response.text()를 리턴하는 로직을 가진 콜백)이 리턴하는 promise객체를 then메서드 자체도 똑같이 리턴한다.
- 다시말해, then메서드가 리턴한 promise객체는, 그 콜백에서 리턴한 promise객체와 동일한 상태와 결과를 가진다.
- 콜백에서 리턴한 pormise객체로부터 새로운 chain이 시작된다는 말이다.
2. promise객체가 아닌 값을 리턴하는 경우
- then메서드가 반환하는 promise객체의 상태는 fulfilled, 작업 성공 결과는 그 값(리턴된 값)을 가진다.
3. 아무것도 리턴하지 않는 경우
- fulfilled상태에, 작업 성공 결과로 undefined를 가지는 promise객체를 리턴한다.
4. rejected된 경우
- promise객체의 상태가 rejected로 변경되고, 작업 실패 정보로 해당 에러 객체를 리턴한다.
5. 아무런 콜백도 실행되지 않은 경우
// Internet Disconnected
fetch('https://www.google.com')
.then((response) => response.text())
.then((result) => { console.log(result) }, (error) => { alert(error) });
- fetch에서 promise객체가 rejected되었는데, 첫번째 then메서드에는 rejected된 경우 실행할 콜백이 등록되어있지 않다.
- 이런 경우, 첫번째 then메서드는 상위의 fetch함수가 리턴한 것과 같은 promise객체를 return한다.
- 그러니까, fetch시 에러가 난 현재 상황에서, 두번째 then메서드도 rejected에 fetch에러를 작업실패정보로 가지고 있는 promise객체를 리턴한다.
- 따라서 두번째 then메서드에서는 rejected된 경우의 콜백이 실행될 것이다.((error) => { alert(error) })
rejected상태가 되면 실행할 콜백 등록
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.text(), (error) => { console.log(error); })
.then((result) => {console.log(result);});
- then메서드로 등록한 콜백은 지금 바로 실행되는 것이 아니라, response가 잘 와서 fetch가 리턴한 promise객체가 fulfilled상태가 되면 실행한다고했다.
- 만약 rejected 상태가 됐을 때에 실행할 콜백도 등록하고 싶다면 위의 코드와 같이 then메서드에 두번째 파라미터로 넣어주면 된다.
- 두번째 파라미터의 파라미터(위 코드에서는 error변수를 의미한다.)는 rejected되었을 때 실행되는 것이기 때문에 작업 실패정보가 담겨있다.
Promise객체가 등장한 이유
- callback Hell문제를 해결한다.
- 비동기 작업 처리에 관해 좀더 세밀한 처리를 자바스크립트 문법단에서 해결한다.
// Promise객체가 없었다면 작성됐을 코드
fetch('https://first.com', (response) => {
// Do Something
fetch('https://second.com', (response) => {
// Do Something
fetch('https;//third.com', (response) => {
// Do Something
fetch('https;//fourth.com', (response) => {
// Do Something
});
});
});
});
// Promise객체가 생김으로써 작성된 코드
fetch('https://first.com')
.then((response) => {
// Do Something
return fetch('https://second.com');
})
.then((response) => {
// Do Something
return fetch('https://third.com');
})
.then((response) => {
// Do Something
return fetch('https://third.com');
});
Promise객체가 없었다면 작성됐을 코드는 fetch안에 fetch가 끝없이 들어가 알아보기 힘들기 때문에 유지보수가 어려워 질 것이다.
반면 Promise객체가 생김으로써 작성된 코드는 Promise Chaining으로 알아보기 편리하다.
Promise객체 직접 만들기
const p = new Promise((resolve, reject) => {
});
- promise객체를 new 키워드로 만들고 있는데, 파라미터로 들어간 함수는 자동으로 실행되는 함수이다.
- executor함수 라고 부른다.
- 이 executor함수는 resolve, reject 두 개의 파라미터를 받고있다.
- resolve : 생성될 promise객체를 fulfilled상태로 만들 수 있는 함수가 연결된다.
- reject : 생성될 promise객체를 rejected상태로 만들 수 있는 함수가 연결된다.
const p = new Promise((resolve, reject) => {
setTimeout(() => {resolve('success');}, 2000);
});
위 코드는 setTimeout함수를 통해 2초후, resolve파라미터로 연결되는 함수(resolve함수라고 부르겠다.)를 실행하도록 하고있다.
이 resolve함수는 promise객체를 fulfilled상태로 만들어주기 때문에, p에 담길 promise객체는 2초 후, fulfilled상태가 된다.
그리고 resolve함수의 파라미터로 들어가있는 'success'라는 문자열은 작업 성공 결과이다.
const p = new Promise((resolve, reject) => {
setTimeout(() => {resolve('success');}, 2000);
});
p.then((result) => { console.log(result) }); // 2초 후 success
p를 rejected상태로 만드려면 아래와 같이 작성할 수 있다.
const p = new Promise((resolve, reject) => {
setTimeout(() => {reject(new Error('fail'));}, 2000);
});
p.catch((error) => { console.log(error) });
rejected된 결과를 출력하기위해서 catch메서드를 사용해야한다.
이미 상태가 결정된 promise객체 만들기
// fulfilled상태의 promise객체 만들기
// 아래 코드는 작업 성공 결과인 success가 출력된다.
const p = Promise.resolve('success');
p.then((result) => { console.log(result); }, (error) => { console.log(error); });
// rejected상태의 promise객체 만들기
// 아래 코드는 작업 실패정보인 Error객체의 내용이 출력된다.
const p = Promise.reject(new Error('fail'));
p.then((result) => { console.log(result); }, (error) => { console.log(error); });
이렇게 상태가 결정된 promise객체는, 한 함수안에서 리턴하는 값이 여러개인 경우, 모두 Promise객체로 통일하고 싶을 때 사용될 수 있다.
unction doSomething(a, b) {
if (problem) {
return Promise.reject(new Error('Fail'));
} else {
return fetch('https://~');
}
}
- 위 코드의 if문 안에서 Promise.reject(new Error) 하는 것을 볼 수 있는데,
- 에러를 Promise객체로 바꾸지 않고 바로 throw할 수도 있지만, 리턴타입을 통일하기 위해서 사용된 모습을 볼 수 있다.
promisify
function wait(text, milliseconds) {
setTimeout(() => text, milliseconds);
}
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.text())
.then((result) => wait(`${result} by Codeit`, 2000)) // 2초 후에 리스폰스의 내용 뒤에 'by Codeit' 추가하고 리턴
.then((result) => { console.log(result); });
- 위 코드를 실행하면 undefined가 출력된다.
- 왜냐하면 wait이라는 함수는 아무것도 리턴하고있지 않기때문이다.
- 원하는 결과를 출력시키려면 아래와같이 수정해야한다.
function wait(text, milliseconds) {
const p = new Promise((resolve, reject) => {
setTimeout(() => { resolve(text); }, 2000);
});
return p;
}
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.text())
.then((result) => wait(`${result} by Codeit`, 2000))
.then((result) => { console.log(result); });
- 이제 wait함수는 promise객체를 리턴하고 있고, response와 문자열이 잘 출력될 것이다.
- 비동기 실행 함수(위 예시에서는 setTimeout)의 콜백이 리턴하는 값을 promiseChain에서 사용하고싶다면,
- 해당 함수를 감싸서 Promise객체를 생성 후, 리턴해줘야한다.
- 이렇게 비동기 실행 함수를 promise객체로 감싸서, 그 promise객체를 리턴하는 형식으로 만드는 작업을 promisify라고 한다.
promisify로 callback hell 벗어나기
// 1개의 파일만 읽고 출력할 때
fs.readFile('file1.txt', 'utf8', (error, data) => {
if (err) {
console.log(err);
} else {
console.log(data);
}
});
// 3개의 파일을 읽고 출력할 때
fs.readFile('file1.txt', 'utf8', (error1, data1) => {
if (error1) {
console.log(error1);
} else {
console.log(data1);
fs.readFile('file2.txt', 'utf8', (error2, data2) => {
if (error2) {
console.log(error2);
} else {
console.log(data2);
fs.readFile('file3.txt', 'utf8', (error3, data3) => {
if (error3) {
console.log(error3);
} else {
console.log(data3);
}
});
}
});
}
});
- 위 코드는 node.js의 readFile이라는 비동기 실행 메서드를 사용해서 파일들을 모두 읽는 로직을 작성한 것이다.
- 파일이 모두 읽어지면 파일내용을 두번째 파라미터로 전달하고, 콜백을 실행한다.
- 파일을 읽다가 에러가 발생하면 첫번째 파라미터로 에러를 전달하고, 콜백을 실행한다.
- file1, file2, file3을 에러가 없이 잘 읽힌 경우, 순차적으로 읽고 싶기때문에 위와같이 가독성이 좋지 않은 코드가 작성되었다.
- Promise객체를 사용하지 않고, 콜백함수를 바로 파라미터에 집어넣는 전통적 형식의 비동기 함수들의 문제가 바로 순차적으로 비동기 실행함수들을 실행하고자 한다면, 콜백안에 또 콜백을 집어넣어야한다는 점이다.
위 코드를 promisify 하면 다음과 같다.
function readFile_promisified(filename) {
const p = new Promise((resolve, reject) => {
fs.readFile(filename, 'utf8', (error, data) => {
if (error) {
reject(error); // 에러 발생 시 -> rejected
} else {
resolve(data); // 파일 내용 읽기 완료 -> fulfilled
}
});
});
return p;
}
readFile_promisified('file1.txt')
.then((data) => {
console.log(data); return readFile_promisified('file2.txt');
})
.then((data) => {
console.log(data); return readFile_promisified('file3.txt');
})
.then((data) => { console.log(data); })
.catch((error) => { console.log(error); });
- readFile_promisified 함수는 promise객체를 반환한다.
- 그리고 파일 읽기를 성공하면, 파일 내용을 console에 찍고, file2를 읽기 시작한다.
- 만약 파일을 읽다가 에러가 발생한다면 catch로 빠져서 에러를 콘솔에 찍을 것이다.
- 이러한 방법으로 promisify해 callback hell을 방지하고 가독성 높은 코드를 작성할 수 있다.
Promisify하면 안되는 함수
콜백을 여러번 실행하는 함수들은 promisify하면 안된다.
예를들면 setInterval, addEventListener.
Promise객체는 한 번 pending상태에서 fulfilled 또는 rejected로 settled되고 나면, 그 뒤로 상태와 결과가 바뀌지 않기 때문이다.
const box = document.getElementById('test');
let count = 0;
function addEventListener_promisified(obj, eventName) { // 이런 Promisify는 하지 마세요
const p = new Promise((resolve, reject) => {
obj.addEventListener(eventName, () => { // addEventListener 메소드
count += 1;
resolve(count);
});
});
return p;
}
addEventListener_promisified(box, 'click').then((eventCount) => { console.log(eventCount); });
- 위 코드는 클릭이벤트를 등록하고있다.
- 클릭이벤트가 발생하면 변수 count + 1을 하고, fulfilled상태로 변화시킨 후, 작업결과로 count + 1을 반환한다.
- resolve(count) 부분이 box를 클릭할 때 마다 실행된다해도, p객체가 가지고 있는 상태와 결과는 변하지 않기때문에,
- then메서드 안의 콜백도 처음 클릭했을 때 딱 한번만 실행 된다.
라고 하지만 사실 이해가 안되어서 좀더 알아봐야겠다.
어쨋든 콜백이 여러번 실행되어야하는 비동기 실행함수는 promisify를 하면 안된다는 것을 알아두자.
Promise객체의 then메서드의 콜백이 실행되는 시점
promise객체의 상태가 pending -> fulfilled 또는 pending -> rejected 로의 상태변화가 생길때 가 아니다.
상태가 이미 결정된 promise객체여도 then메서드를 사용하면 언제든 결과를 추출할 수 있다.
그러니까 promise객체는 그냥 객체고, then메서드가 그 객체를 가져와서 pending이면 기다리고 settled되었으면 그 결과를 꺼내쓴다는 말인것 같다.
event click하기전에 addEventLisetener를 해놔야 클릭 순간에 이벤트가 발생하는 것 마냥
변화시점에 then이 붙어있어야만 콜백이 실행되는 것이 아니다.
Promise객체를 리턴하는 함수들
1. fetch()
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.text())
.then((result) => {console.log(result);});
2. text()
- fetch 함수로 response를 잘 받으면, response객체의 text메소드는 fulfilled상태이면서 리스폰스의 바디에있는 내용을 string타입으로 변환한 값을 '작업 성공 결과' 로 가진 promise객체를 리턴한다.
- 이 때 작업 성공 결과는 string타입이고, 만약 이 값이 JSON데이터라면 deserialize해줘야한다. (=JSON.parse해줘야한다.)
3. json()
- fetch함수로 response를 잘 받으면, response객체의 json메소드는 fulfilled상태이면서 리스폰스의 바디에있는 JSON데이터를 자바스크립트 객체로 Deserialize해서 생겨난 객체를 '작업 성공 결과’로 가지는 promise객체를 리턴한다.
- 만약 리스폰스의 바디에 있는 내용이 JSON타입이 아니라면 에러가 발생하고 Promise객체는 rejected상태가 되면서 '작업 실패 정보’를 갖게 된다.
에러 처리하기
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.text())
.catch((error) => {console.log(error)})
.then((result) => {console.log(result);}
);
catch메서드를 사용해서 promise객체의 상태가 rejected가 됐을 때 실행시킬 콜백을 등록할 수 있다.
앞서 배운 것과 같이, then메서드의 두번째 인자로 콜백을 넣는 것과 같은 동작을 한다.
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.text())
.then(undefined, (error) => {console.log(error)})
.then((result) => {console.log(result);
});
위 2개의 코드는 같은 동작을 하는 코드이다.
catch메서드로 rejected됐을 때의 콜백을 등록할 것인지, 아니면 then메서드의 두번째 인자로 콜백을 등록할 것인지의 차이이다.
then메서드의 첫번째 인자로 undefined를 넣고, 두번째 인자에만 콜백을 넣음으로 catch메서드와 같은 기능을 한다는 것을 알 수 있다.
catch메서드는 보통 가장 아래에 써서 윗쪽 then메서드들에서 일어나는 모든 에러를 잡을 수 있도록 하는 편이다.
하지만 중간의 catch문에서 특정 에러에 대한 대안을 낼 것이라면 중간에 쓰는 경우도 있다.
fetch('https://friendbook.com/my/newsfeeds')
.then((response) => response.json())
.then((result) => {
const feeds = result;
return processedFeeds;
})
.catch((error) => {
const storedGeneralNews = getStoredGeneralNews();
return storedGeneralNews;
})
.then((result) => { console.log(result); })
.catch((error) => { console.log(error); });
위 코드와 같이 중간에 catch를 넣어서 fetch가 리턴한 promise객체가 rejected된다면, 새로운 함수를 실행시키도록 할 수 있다는 의미이다.
finally
promise객체의 상태가 fulfilled가 되던, rejected가 되던 상관 없이 실행시켜야하는 로직이 있다면, finally메서드를 사용해서 등록한다.
보통 catch메서드 뒤에 가장 마지막에 작성한다.
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.text())
.then((result) => {console.log(result);})
.catch((error) => {console.log(error)})
.finally(() => {console.log('exit')}
);
finally메서드는 작업 성공 결과나, 작업 실패 정보가 필요하지 않기때문에 파라미터가 없다.
+) pending상태를 벗어나 fulfilled 또는 rejected상태가 되는 것을 settled 됐다고 말한다.
여러 Promise객체를 다루는 방법
1. all 메서드
// 1번 직원 정보
const p1 = fetch('https://learn.codeit.kr/api/members/1').then((res) => res.json());
// 2번 직원 정보
const p2 = fetch('https://learn.codeit.kr/api/members/2').then((res) => res.json());
// 3번 직원 정보
const p3 = fetch('https://learn.codeit.kr/api/members/3').then((res) => res.json());
Promise
.all([p1, p2, p3])
.then((results) => {
console.log(results); // Array : [1번 직원 정보, 2번 직원 정보, 3번 직원 정보]
});
all메서드도 then메서드처럼 새로운 promise객체를 리턴한다.
all메서드는 이렇게 아규먼트로 들어온 배열 안에 있는 모든 Promise객체가 pending상태에서 fulfilled상태가 될때까지 기다린다.
모든 promise객체들이 fulfilled 상태가 되면, all메서드가 리턴했던 promise객체는 fulfilled상태가 되고,
각 Promise객체의 작업 성공 결과들로 이루어진 배열을 그 작업 성공 결과로 갖게 된다.
그러니까, all메서드가 리턴한 promise객체는 각각 p1, p2, p3이 작업성공한 결과의 배열이다.
all은 파라미터로 받은 배열의 모든 비동기결과가 성공이 될때까지 기다렸다가 취합하기 위해 사용한다.
만약 하나라도 rejected된다면
all이 반환하는 promise객체의 상태도 rejected고 동일한 작업 실패 정보를 갖게 된다.
하나라도 rejected되면 전체 작업이 실패한 것으로 간주된다.
그리고 하나라도 rejected가 될 경우를 대비해서 catch메서드를 붙여준다면 아래와 같이 작성할 수 있다.
// 1번 직원 정보
const p1 = fetch('https://learn.codeit.kr/api/members/1').then((res) => res.json());
// 2번 직원 정보
const p2 = fetch('https://learn.codeit.kr/api/members/2').then((res) => res.json());
// 3번 직원 정보
const p3 = fetch('https://learnnnnnn.codeit.kr/api/members/3').then((res) => res.json());
Promise
.all([p1, p2, p3])
.then((results) => {
console.log(results); // Array : [1번 직원 정보, 2번 직원 정보, 3번 직원 정보]
})
.catch((error) => {
console.log(error);
});
2. race 메서드
all메서드와 마찬가지로 여러 Promise객체들이 있는 배열을 아규먼트로 받는다.
그리고 race메서드도 all메서드처럼 Promise객체를 리턴한다.
race메서드가 리턴한 Promise객체는 아규먼트로 들어온 배열의 여러 Promise객체들 중에서
가장 먼저 fulfilled상태 또는 rejected상태가 된 Promise객체와 동일한 상태 결과를 갖게된다.
말 그대로 race를 시켜 가장 빨리 pending상태를 벗어난 promise객체와 같은 결과/상태를 반환하는 것이다.
const p1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Success'), 1000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('fail')), 2000);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('fail2')), 4000);
});
Promise
.race([p1, p2, p3])
.then((result) => {
console.log(result); // success 출력
})
.catch((value) => {
console.log(value);
});
위 코드는 p1이 1초만에 fulfilled상태가 되었기때문에 'success'를 출력하게된다.
만약 p2가 [ setTimeout(() => reject(new Error('fail')), 500); ] 이런 로직을 가졌더라면, 콘솔에는 에러 'fail'이 찍혔을 것이다.
3. allSettled 메서드
- 배열내의 모든 Promise객체가 settled상태가 되기까지 기다렸다가, pending상태가 하나도 없게되면 fulfilled상태가 된다.
- all메서드와 비교해보자면, all메서드는 모든 Promise객체들이 fulfilled가 되기를 기다리고,
- allSettled메서드는 모든 Promise객체들이 settled되기를 기다린다.
그 작업 성공결과로, 하나의 배열을 갖게 되는데, 이 배열에는 아규먼트로 받았던 배열 내의 각 promise 객체의
- 최종 상태(status 프로퍼티)
- 작업 성공 결과(value 프로퍼티)
- 작업 실패 정보(reason 프로퍼티)
를 담은 객체들이 요소로 담긴다.
[
{status: "fulfilled", value: 1},
{status: "fulfilled", value: 2},
{status: "fulfilled", value: 3},
{status: "rejected", reason: Error: an error}
]
4. any 메서드
- 여러 Promise객체들 중에서 가장 먼저 fulfilled상태가 된 Promise객체의 상태/결과를 반영해 리턴한다.
- 만약 모든 Promise객체가 rejected상태가 되어버리면, AggregateError라고 하는 에러를 작업 실패 정보로 갖고, rejected상태가 된다.
- any라는 단어의 뜻 처럼 배열속의 Promise객체 중 단 하나라도 fulfilled상태가 되면 리턴한다.
- race메서드와 비교해보자면, race메서드는 가장 먼저 settled되는 객체를 리턴하고,
- any메서드는 가장먼저 fulfilled되는 객체를 리턴한다.
axios
fetch함수와 사용법도 비슷하고, axios객체를 사용해 리퀘스트를 보내는 많은 메서드들이 fetch처럼 Promise객체를 리턴하는 점도 비슷하다.
다만, axios 객체에는 fetch 함수에는 없는 기능 및 장점 몇가지를 적어보자면 아래와 같다.
- 모든 리퀘스트, 리스폰스에 대한 공통 설정 및 공통된 전처리 함수 삽입 가능
- serialization, deserialization을 자동으로 수행
- 특정 리퀘스트에 대해 얼마나 오랫동안 리스폰스가 오지 않으면 리퀘스트를 취소할지 설정 가능(request timeout)
- 업로드 시 진행 상태 정보를 얻을 수 있음
- 리퀘스트 취소 기능 지원
단점으로는 별도의 다운로드가 필요한 패키지라는 점이 있다.
그래서 axios에서 제공하는 추가 기능이 필요한 경우에는 axios를 쓰고,
그런 기능이 필요하지 않고 별도의 패키지 다운로드를 원하지 않는 경우에는 fetch 함수를 사용.
'JavaScript' 카테고리의 다른 글
JavaScript - 비동기실행 순서 예제 (1) | 2023.10.15 |
---|---|
JavaScript - async/await (1) | 2023.10.13 |
JavaScript - API(response data, REST API, contnet-type 등) (0) | 2023.10.13 |
JavaScript - 웹과 통신 (0) | 2023.10.13 |
JavaScript - 모듈화 (0) | 2023.10.11 |