[JS]-DeepDive 프로미스

Kng_db·2023년 3월 31일
0

자바스크립트는 비동기 처리를 위한 하나의 패턴으로 콜백 함수를 사용합니다.

  • 전통적인 콜백 패턴의 단점
  1. 콜백 핼(콜백 지옥)로 인해 가독성이 나쁩니다.

  2. 비동기 처리 중 발생한 에러의 처리가 어렵습니다.

  3. 여러 개의 비동기 처리를 한번에 처리하는 것에 한계가 있습니다.


  • 비동기 함수

비동기 함수란 함수 내부에 비동기로 동작하는 코드를 포함한 함수를 말합니다.

비동기 함수를 호출하면,
함수 실행 -> 함수 내부 비동기 동작(완료x) -> 함수 종료 -> 함수 내부 비동기 동작(완료o)
따라서 비동기 함수 내부의 비동기로 동작하는 코드에서 처리 결과를 외부로 반환하거나 상위 스코프의 변수에 할당하면 결과대로 동작하지 않습니다.


ES6에서는 비동기 처리를 위한 패턴으로 프로미스를 도입합니다.

Promise

프로미스는 전통적인 콜백 패턴이 가진 단점을 보완하며 비동기 처리 시점을 명확하게 표현할 수 있습니다.

  1. 제작 코드는 원격에서 스크립트를 불러오는 것 같은, 시간이 걸리는 일을 합니다.

  2. 소비 코드는 제작 코드의 결과를 기다렸다가 이를 소비합니다. 소비 주체(함수)는 여럿이 될 수 있습니다.

  3. 프로미스는 제작 코드와 소비 코드를 연결해 주는 자바스크립트 객체입니다.
    시간이 얼마나 걸리든 상관없이 약속한 결과를 만들어 내는 제작 코드가 준비되었을 때, 모든 소비 코드가 결과를 사용할 수 있도록 해줍니다.

프로미스 객체는 다음과 같은 문법으로 만들 수 있습니다.

프로미스에 전달되는 함수는 executor(실행 함수, 콜백 함수) 라고 부릅니다. executor는 프로미스가 만들어질 때 자동으로 실행되는데, 결과를 최종적으로 만들어내는 제작 코드를 포함합니다.

콜백 함수의 인수 resolvereject 함수는 자바스크립트에서 자체 제공하는 함수(콜백)입니다. resolve와 reject는 신경 쓰지 말고 실행 함수 내부 코드만 작성하면 됩니다.

실행 함수에선 결과를 상황에 따라 인수로 넘겨준 함수 중 하나를 반드시 호출해야 합니다.

  • Promise 생성자 함수가 인수로 전달받은 콜백 함수 내부에서 비동기 처리를 수행

  • resolve(value) : 비동기 처리가 성공하면 그 결과를 나타내는 value와 함께 호출합니다.

  • reject(error) : 비동기 처리가 실패하면 error와 함게 호출합니다.

" executor(콜백 함수)는 자동으로 실행됩니다. 여기서 처리가 끝나면 성공 여부에 따라 resolve나 reject를 호출합니다. "


  • 프로미스 객체가 갖는 내부 프로퍼티

  • state - pending(대기), fulfilled(성공), rejected(실패)

  • result - undefined, resolve(value), reject(error)

따라서 executor는 프로미스의 상태를 둘 중 하나로 변화시킵니다.

  1. 선언함과 동시에 콜백 함수는 new Promise에 의해 호출됩니다.
  1. 콜백 함수는 인자로 resolve와 reject 중 하나는 반드시 호출합니다.
  1. 처리가 시작 된 지 1초 후, resolve("완료")가 호출되고 결과에 의해 프로미스 객체의 상태가 변합니다.
  • settled - fulfilled(성공) 또는 rejected(실패) 상태를 settled 상태라고 합니다. pending(대기)이 아닌 상태로 비동기 처리가 수행된 상태를 말하며, 프로미스는 settled 상태가 되면 다른 상태로 변화할 수 없습니다.

" 프로미스는 비동기 처리 상태와 처리 결과를 관리하는 객체입니다. "


Promise의 후속 처리 메서드

then

then은 프로미스에서 가장 중요하고 기본이 되는 메서드입니다.
then은 두개의 콜백 함수를 인수로 전달받습니다.

  • 첫 번째 콜백 함수는 프로미스가 fulfilled 상태가 되면 호출됩니다. 이때 콜백 함수는 프로미스의 비동기 처리 결과를 인수로 전달받습니다.

  • 두 번째 콜백 함수는 프로미스가 rejected 상태가 되면 호출됩니다. 이때 콜백 함수는 프로미스의 에러를 인수로 전달받습니다.

catch

에러가 발생한 경우만 다루고 싶다면 .then(null, 에러함수)와 같이 null을 첫 번째 인수로 전달해도 됩니다. catch(에러함수)와 동일하게 작동합니다.
그래서 catch는 한 개의 콜백 함수를 인수로 전달받습니다.

finally

finally는 then과 유사합니다. 하지만 결과가 어떻든 마무리가 필요하면 finally가 유용합니다.
finally 메서드는 한 개의 콜백 함수를 인수로 전달받습니다.

" then, catch, finally는 체이닝이 가능합니다. "


Promise의 정적 메서드

프로미스는 주로 생성자 함수로 사용 됩니다. 함수도 객체이므로 메서드를 가집니다.

  • 프로미스의 5가지 정적 메서드
  1. Promise.resolve/reject : 인수로 전달받은 값을 resolve하는 프로미스를 생성합니다.

  1. Promise.all : 여러 개의 비동기 처리를 모두 병렬 처리할 때 사용합니다.

  1. Promise.race : Promise.all 메서드와 동일하게 프로미스를 요소로 갖는 배열 등의 이터러블을 인수로 전달받습니다. 모든 프로미스가 fulfilled 상태가 되는 것을 기다리는 것이 아니라 가장 먼저 fulfilled 상태가 된 프로미스의 처리 결과를 resolve하는 새로운 프로미스를 반환합니다.

  1. Promise.allSettled : 프로미스를 요소로 갖는 배열 등의 이터러블을 인수로 전달받습니다. 전달받은 프로미스가 모두 settled 상태(비동기 처리가 수행된 상태)가 되면 처리 결과를 배열로 반환합니다.


마이크로태스크 큐

프라미스 핸들러 .then/catch/finally는 항상 비동기적으로 실행됩니다.

프라미스가 즉시 이행되더라도 .then/catch/finally 아래에 있는 코드는 이 핸들러들이 실행되기 전에 실행됩니다.

프로미스의 후속 처리 메서드의 콜백 함수는 태크스 큐가 아니라 마이크로태스크 큐에 저장됩니다.

  • 마이크로태스크큐 : 태스크 큐보다 우선순위가 높습니다.
    이벤트 루프는 콜 스택이 비면 마이크로태스크 큐 함수 실행 -> 태스크 큐 함수 실행

마이크로태스크 큐는 먼저 들어온 작업을 먼저 실행합니다(FIFO, first-in-first-out).
실행할 것이 아무것도 남아있지 않을 때만 마이크로태스크 큐에 있는 작업이 실행되기 시작합니다.


fetch

HTTP 요청 전송 기능을 제공하는 클라이언트 사이드 Web API입니다.

fetch 함수는 프로미스를 지원하기 때문에 비동기 처리를 위한 콜백 패턴의 단점에서 자유롭습니다.
fetch 함수는 HTTP 응답을 나타내는 Response 객체를 래핑한 Promise 객체를 반환합니다.

  • 일반적인 fetch 요청은 두 개의 await 호출로 구성됩니다.

  • await 없이 호출

  • 응답 객체의 프로퍼티

response.status – 응답의 HTTP 코드
response.ok – 응답 상태가 200과 299 사이에 있는 경우 true
response.headers – 맵과 유사한 형태의 HTTP 헤더

  • 응답 본문 요청 메서드

response.text() – 응답을 텍스트 형태로 반환함
response.json() – 응답을 파싱해 JSON 객체로 변경함
response.formData() – 응답을 FormData 객체 형태로 반환(form/multipart 인코딩에 대한 내용은 다음 챕터에서 다룸)
response.blob() – 응답을 Blob(타입이 있는 바이너리 데이터) 형태로 반환
response.arrayBuffer() – 응답을 ArrayBuffer(바이너리 데이터를 로우 레벨로 표현한 것) 형태로 반환

  • fetch의 옵션

method – HTTP 메서드
headers – 요청 헤드가 담긴 객체(제약 사항이 있음)
body – 보내려는 데이터(요청 본문)로 string이나 FormData, BufferSource, Blob, UrlSearchParams 객체 형태


참고 https://ko.javascript.info/promise-basics

profile
코딩 즐기는 사람

0개의 댓글