[Day 14] 콜백 대체 비동기 기능

thru·2023년 6월 20일
1

FEDC-TIL

목록 보기
13/21

if (!response.ok)


오늘 공부한 내용 ☁️

오늘은 콜백 지옥을 극복하기 위해 도입된 비동기 기능 중 Promise와 async, await에 대해 배웠다.
또한 네트워크 요청을 보낼 수 있는 API인 fetch의 사용법을 알게 되었다.


새로 알게된 내용 🌱

fetch

기존에 사용하던 콜백 기반의 XMLHttpRequest를 편하게 사용할 수 있도록 Promise 기반으로 개선한 대체제이다.

첫 번째 인자로는 url을, 두 번째 인자로는 객체의 형태로 각종 옵션을 전달할 수 있다.
옵션에 아무것도 넘기지 않으면 자동으로 요청이 GET으로 진행된다.

응답은 두 단계로 진행된다.
먼저 서버에서 응답 헤더를 받으면 fetch 호출 시 반환받은 promise가 Response 객체와 함께 resolve된다.
다음엔 추가 메서드를 호출해서 본문을 받아 처리한다.

첫 번째 단계에서는 헤더의 statusok 값을 보고 요청의 성공 여부를 판단할 수 있다.
fetch는 네트워크 오류나 서버의 CORS 설정이 잘못된 경우에만 reject한다.
status code 300 이상과 같이 원하는 응답이 아닌 경우에도 resolve를 해서 넘겨버린다.

어쨌든 응답이죠

때문에 헤더의 값을 보고 성공 여부를 판단해서 에러 처리를 해주는 게 필요하다.
ok는 status 코드가 200번대일 경우에만 true로 나타나는 속성이다.

두 번째 단계에서는 Response 객체에서 본문을 뽑아내서 사용해야한다.
사용하고 싶은 형태에 따라 .text(), .json(), .blob() 등의 메서드를 호출한다.
메서드를 한번 호출하면 본문은 처리된 상태가 되기 때문에 다시 호출할 수 없다.

두 단계 모두 비동기적 처리가 필요한데 두 개의 .then으로 처리할 수도 있고, 두 개의 await로 처리할 수도 있다.


리마인드된 내용 🔨

Promise

비동기 작업을 제어하기 위해 나온 개념으로 Callback에 비해 depth 조절이 용이하다.

new Promise(함수)문법의 생성자로 만들 수 있는데 전달되는 함수는 executor라고 한다.
executor는 인자로 resolvereject라는 자체적으로 제공되는 콜백을 가진다. executor가 결과를 내면 상황에 맞게 두 콜백 중 하나는 호출되어야 한다.
resolve의 경우 일이 성공적으로 처리된 경우 결과 값과 함께 호출되고, reject의 경우 에러가 발생했을 때 에러 객체와 함께 호출된다.

생성자가 반환한 promise 객체는 내부적으로 stateresult라는 속성을 갖는다.
처음에는 각각 "pending", undefined의 값을 가지다가 resolve 가 호출되면 "fulfilled"와 결과 값이 되고, reject가 호출되면 "rejected"와 에러 객체가 된다.

executor의 결과로 변화된 두 속성은 아래의 소비함수들을 통해 사용할 수 있다.

.then의 경우 일반적으로 첫 번째 인자로 함수를 받고, 그 함수는 resolve를 통해 온 결과 값을 인자로 받는다. 이 함수는 핸들러라고 부른다.
이를 통해 이전 작업이 성공했을 때 수행할 작업을 등록할 수 있다.
두 번째 인자도 함수로 지정해주면 reject 이후의 예외처리 작업도 등록할 수 있다.

.catch.then에서 두 번째 인자만 전달한 것과 완전히 동일하다.

.finally는 resolve나 reject 여부와 관계없이 무조건 실행할 작업을 등록하는데 사용한다.
따라서 핸들러가 인자를 받지않아 결과 값이나 에러 객체를 접근할 수는 없다. 다만 뒤로 전달은 해준다.

pass thru~

소비함수도 생성자와 마찬가지로 promise 객체를 반환하므로 쭉 이어서 작업을 처리할 수 있다. 이러한 과정을 promise chaining이라고 한다.
이는 비동기 작업들이 순차적으로 실행되어야 할 때 유용하게 사용할 수 있다.
Callback은 이러한 경우에 depth가 늘어나며 지옥이 열리지만 promise는 뒤로 쭉 늘어쓰면 돼서 depth가 늘어나지 않는다.

chaining이 되어있을 때 reject로 에러가 발생한 경우 이어진 소비함수 중 이를 처리할 수 있는 가장 가까운 함수로 이동한다. 만약 그런 함수가 없다면 전역 에러로 넘어가서 프로그램이 죽는다.

all이나 race 같은 Promise 메서드를 통해 여러개의 promise 객체들을 묶어서 처리할 수도 있다.


느낀점 🎬

fetch는 멋모를 때 써본적은 있는 것 같은데 주의할 점이 있다는 건 몰랐었다.
Promise는 콜백보다 낫긴 하지만 여전히 좀 복잡하긴 한 것 같다. catch는 원래 뒤에 하나만 달 수 있는 줄 알았는데 then이랑 섞어서 쓸 수 있다는 건 처음 알았다.


참조


profile
프론트 공부 중

2개의 댓글

comment-user-thumbnail
2023년 6월 22일

짤 부자 호원님 ㅋㅋ 항상 재미있게 보고 있습니다 ㅎㅎ

1개의 답글