fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.text())
.then((result) => {console.log(result); });
위 코드와 같이, then
method 뒤에는 계속해서 then
method를 붙일 수 있으며,
이렇게 promise
객체에 then
method를 연속적으로 붙이는 것을 Promise Chaining
이라고 한다.
생각해보면, promise
객체는 fetch
함수가 리턴하는 객체 하나 말고는 존재하지 않는데, 왜 여러 개의 promise
객체가 있는 것처럼 then
method를 계속 붙일 수 있는 것일까?
그 이유는, then
method가 새로운 promise
객체를 리턴하기 때문이다.
다시 말하면, 연속적으로 붙어있는 각각의 then
method들은 별개의 promise
객체를 리턴하고 있는 것이다.
여기서 하나 기억해야 하는 점은, then
method가 리턴한 promise
객체는 가장 처음에는 pending
상태라는 것이다.
이후 then
method에 등록된 콜백 함수가 실행되어 리턴 값이 생성되면, then
method가 리턴했던 promise
객체가 영향을 받아 상태가 바뀌게 되는 것이다.
이 때, 다음과 같은 상황들이 발생할 수 있다.
콜백 안에서 promise
객체를 리턴하는 경우, then
method가 리턴한 promise
객체가 콜백 함수가 리턴한 promise
객체와 동일한 상태와 결과를 갖게 된다.
- 아래 예시에서, text
method는 promise
객체를 리턴하는 method로, response
를 잘 받게 되면, text
method가 리턴하는 promise
객체는 fulfilled
상태이고, 그 작업 성공 결과로 response의 내용을 갖고 있는 것이다. 이로 인해, then
method가 리턴한 promise
객체도 이와 동일한 fulfilled
상태와 결과를 갖게 되는 것이다.
콜백 안에서 promise
객체가 아닌 값, 예를 들면 숫자, 문자열, 일반 객체 등의 값을 리턴하는 경우, then
method가 리턴했던 promise
객체는 fulfilled
상태가 되고, 콜백 함수의 리턴 값을 작업 성공 결과로 갖게 된다.
실행된 콜백이 아무 값도 리턴하지 않는 경우, 자바스크립트에서는 함수가 아무것도 리턴하지 않으면 undefined
를 리턴한 것으로 간주되기 때문에, 결과적으로 then
method가 리턴했던 promise
객체는 fulfilled
상태가 되고, 그 작업 성공 결과로 undefiend
를 갖게 된다.
실행된 콜백 내부에서 에러가 발생한 경우, promise
객체가 rejected
상태가 되고, 작업 실패 정보로 해당 Error
객체를 갖게 된다.
- 에러가 발생하는 상황으로는, 정의하지 않은 함수를 콜백하는 경우 또는 인위적으로 throw
문을 사용해서 에러를 발생시키는 경우 등이 있다.
아무런 콜백도 실행되지 않을 경우에는, 이전 promise
객체와 동일한 상태와 결과를 같게 된다.
- 아래 예시 코드를 보면, 인터넷 연결이 끊겨있는 상황으로 가정했기 때문에, Promise-1
객체는 rejected
상태가 되는데, 첫 번째 then
method에는 두 번째 파라미터가 존재하지 않기 때문에, 아무런 콜백도 실행되지 않는다. 이 경우, Promise-2
객체는 이전 promise
객체와 동일한 상태와 결과를 갖기 때문에, Promise-1
객체처럼 rejected
상태가 되며, 동일한 작업 실패 정보를 갖게 되는 것이다. 때문에, 결과적으로 두 번째 then
method의 두 번째 콜백 함수가 실행된다.
// Internet Disconnected
fetch('https://www.google.com') // Promise-1
.then((response) => response.text()) // Promise-2
.then((result) => { console.log(result) }, (error) => { alert(error) });
Promise Chaining은 비동기 작업을 순차적으로 수행해야 할 때, 전체 코드를 좀 더 깔끔하게 나타내기 위해 사용한다.