이전 포스팅에서 콜백에서 순차적으로 비동기작업을 처리할 때 콜백지옥을 보셨던 것 기억하시나요?
프로미스에선 순차적으로 처리해야하는 비동기 작업이 여러개 있을때 어떻게 해야할까요?
프라미스 체이닝을 통한 비동기 처리를 이용한다면 어렵지 않습니다.
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000); // (1)
}).then(function(result) { // (2)
alert(result); // 1
return result * 2;
}).then(function(result) { // (3)
alert(result); // 2
return result * 2;
}).then(function(result) {
alert(result); // 4
return result * 2;
});
위 예시는 아래와 같은 순서로 실행됩니다.
- 1초 후 최초 프라미스가 이행됩니다. – (1)
- 이후 첫번째 .then 핸들러가 호출됩니다. –(2)
- 2에서 반환한 값은 다음 .then 핸들러에 전달됩니다. – (3)
- 이런 과정이 계속 이어집니다.
프라미스 체이닝이 가능한 이유는 promise.then을 호출하면 프라미스가 반환되기 때문입니다. 반환된 프라미스엔 당연히 .then을 호출할 수 있습니다.
프로미스 반환하기
.then(handler)에 사용된 핸들러가 프라미스를 생성하거나 반환할수 있습니다.
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000);
}).then(function(result) {
alert(result); // 1
return new Promise((resolve, reject) => { // (1)
setTimeout(() => resolve(result * 2), 1000);
});
}).then(function(result) { // (2)
alert(result); // 2
return new Promise((resolve, reject) => {
setTimeout(() => resolve(result * 2), 1000);
});
}).then(function(result) {
alert(result); // 4
});
예시에서 1을 출력하고 (1)를 반환합니다. 이후 1초가 지나 프라미스가 이행되고 두 번째 .then으로 전달됩니다. 이런식으로 계속되어 최종적으로 4가 출력됩니다. 아까와 다른 점은 단지 1초 딜레이가 생길 뿐입니다.
이렇게 .then은 promise를 반환하는 것이 가능합니다.
fetch와 체이닝
네트워크 요청 시 프라미스를 많이 사용하고, 데이터를 쓰기 위해 여러 체이닝이 붙는 경우가 많습니다. 이를 위한 간단한 예시를 보여드리겠습니다.
let promise = fetch(url) 가 기본적인 fetch의 문법입니다.
위 코드는 url에 네트워크 요청을 보내고 프라미스를 반환하게 됩니다. 원격 서버가 헤더와 함께 응답을 보내면, 프라미스는 response 객체와 함께 이행합니다.
// response.json()은 원격 서버에서 불러온 내용을 JSON으로 변경해줍니다.
fetch('/article/promise-chaining/user.json')
.then(response => response.json())
.then(user => alert(user.name)); // Violet-Bora-Lee, 이름만 성공적으로 가져옴
정보를 이렇게 불러와서 가공할 수 있겠죠?
또 다른 예시하나 보여 드리고 마무리 하겠습니다.
이렇게 하면 과정을 분리하며 로직을 분리 시킬 수 있으니 체이닝은 잘 쓰면 좋을 것 같습니다.
fetch(~~~)
.then(response => response.json())
.then(user => fetch(`~~~`))
.then(response => response.json())
.then(User => new Promise(function(resolve, reject) { // (*)
let img = document.createElement('img');
setTimeout(() => {
img.remove();
resolve(1); // (**)
}, 3000);
}))
.then(res => alert(`성공적으로 실행였습니다.`));
'Front-end > Javascript' 카테고리의 다른 글
JS 스크립트 (0) | 2023.08.03 |
---|---|
Promise API (0) | 2023.08.03 |
Callback (0) | 2023.08.01 |
이벤트 위임 (0) | 2023.07.28 |
이벤트 버블링과 이벤트 캡처링 (0) | 2023.07.26 |