[JavaScript]프라미스 체이닝
순차적으로 처리해야 하는 로직이 여러개 있다면 어떻게 해야할까?
--> 프라미스 체이닝을 이용할 수 있다.
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000); // (*)
}).then(function(result) { // (**)
alert(result); // 1
return result * 2;
}).then(function(result) { // (***)
alert(result); // 2
return result * 2;
}).then(function(result) {
alert(result); // 4
return result * 2;
});
위의 프라미스 체이닝은 다음과 같은 순서로 실행된다.
- 1초 후 최초 프라미스가 이행된다. – (*)
- 이후 첫번째 .then 핸들러가 호출된다. –(**)
- 2에서 반환한 값은 다음 .then 핸들러에 전달된다. – (***)
또한 result가 핸들러 체인을 따라 전달되므로, alert 창엔 1, 2, 4가 순서대로 출력된다.
프라미스 체이닝이 가능한 이유는 promise.then을 호출하면 계속 프라미스가 반환되기 때문에 계속해서 그 프라미스에 .then을 이어서 호출할 수 있기 때문이다.
❌여기서 잠깐❌
프라미스 하나에 여러개의 .then을 추가한 것은 프라미스 체이닝이 아니다.
이건 그냥 프라미스 하나에 등록된 핸들러가 여러개인 것이다. 이 ,.then로직들은 순차적으로 처리되지 않고 독립적으로 처리된다.
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000);
});
promise.then(function(result) {
alert(result); // 1
return result * 2;
});
promise.then(function(result) {
alert(result); // 1
return result * 2;
});
promise.then(function(result) {
alert(result); // 1
return result * 2;
});
1. 프라미스 반환하기
.then(handler)에 사용된 핸들러가 프라미스를 생성하거나 반환하는 경우도있다. 이 경우 핸들러(이어지는 .then)는 프라미스가 처리될 때까지 기다렸다가 처리가 완료되면 그 결과를 받는다.
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000);
}).then(function(result) {
alert(result); // 1
return new Promise((resolve, reject) => { // (*)
setTimeout(() => resolve(result * 2), 1000);
});
}).then(function(result) { // (**)
alert(result); // 2
return new Promise((resolve, reject) => {
setTimeout(() => resolve(result * 2), 1000);
});
}).then(function(result) {
alert(result); // 4
});
예시에서 첫 번째 .then은 1을 출력하고 new Promise(…)를 반환((*))한다.
1초 후 이 프라미스가 이행되고 그 결과(resolve의 인수인 result * 2)는 두 번째 .then으로 전달된다.
두 번째 핸들러((**))는 2를 출력하고 동일한 과정이 반복된다.
따라서 얼럿 창엔 이전 예시와 동일하게 1, 2, 4가 차례대로 출력되지만, 얼럿 창 사이에 1초의 딜레이가 생깁니다.
이렇게 핸들러 안에서 프라미스를 반환하는 것도 비동기 작업 체이닝을 가능하게 해준다는것!
2. fetch와 체이닝 응용하기
프론트 단에서는, 네트워크 요청시 프라미스를 자주 사용한다.
let promise = fetch(url);
// 위 코드를 실행하면 url에 네트워크 요청을 보내고 프라미스를 반환한다. (fetch는 프라미스를 반환하는 함수)
위 코드를 실행하면 url에 네트워크 요청을 보내고 프라미스를 반환한다. 원격 서버가 응답을 보내면, 프라미스는 response 객체와 함께 이행된다.
fetch('/article/promise-chaining/user.json')
.then(function(response) {
return response.text();
})
.then(function(text) {
// 원격에서 받아온 파일의 내용
alert(text); // 텍스트의 내용
});
'/article/promise-chaining/user.json'에서의 원격서버가 응답하면 .then 아래 코드가 실행된다. 첫번째 .then에서는 받아온 데이터의 전체 내용을 읽는 메서드인 response.text()의 결과값을 반환한다. 그럼 두번째 .then에서는 데이터의 전체 내용이 text라는 파라미터로 들어가고 alert창에 출력된다.