프로미스와 비동기 프로그래밍

BackEnd_Ash.log·2021년 3월 28일
0

자바스크립트

목록 보기
21/29

업데이트 2021.08.31 타입스크립트 return Promise<>

https://www.youtube.com/watch?v=JB_yU6Oe2eE
https://www.youtube.com/watch?v=CA5EDD4Hjz4

node.js 는 이벤트 대신 콜백을 사용하여 자바스크립트 비동기 프로그래밍을 더욱 대중화 했다.

📌비동기 프로그래밍 ?

자바스크립트 엔진은 싱글 스레드 이벤트 루프 개념을 기반으로 한다.
이벤트 루프는 자바스크립트 엔진 내의 프로세스이며 , 코드 실행을 감시하고 작업큐를 관리한다.

👉콜백패턴

readFile("example.txt" , function(err , contents){
  if (err){
    	throw err;
  }  
  console.log(contents);
});
console.log("hi");

readFile() 함수는 디스크에서 example.txt 을 읽는다.
작업이 완료되면 두번째 인자인 콜백을 실행한다.

만약 에러가 발생한다면 콜백의 err 인자는 에러 객체일 것이다.
그렇지 않다면 contents 인자는 문자열 파일 콘텐츠를 포함한다.

자바스크립트에서는 비동기 프로그래밍의 한가지 방식으로 callback 패턴을 많이 사용했다.
콜백 패턴은 비동기 작업이 길어질수록 콜백이 깊어지고 , 또한 에러 핸들링 및 디버깅이 어렵다.

function callback() {
  asyncFunc1(result => {
    asyncFunc2(result => {
      asyncFunc3(result => {
        asyncFunc4(result => {
          asyncFunc5(result => console.log('success!'), result);
        }, result)
      }, result)
    }, result)
  })
}
             
callback();

👉프로미스

콜백의 문제점을 해결하기 위해 Promise 패턴이 등장했다.
비동기 작업을 콜백이 아닌 then 으로 연결하고 , catch 로 에러 핸들링 및 디버깅을 편하게 할 수 있다.

function promise() {
  asyncFunc1()
    .then(result => asyncFunc2(result))
    .then(result => asyncFunc3(result))
    .then(result => asyncFunc4(result))
    .then(result => asyncFunc5(result))
    .then(result => console.log('success!'))
    .catch(error => console.log('error!'));
}

promise();

👉생명주기

각 프로미스는 비동기 연산이 아직 완료되지 않았음을 가리키는 보류(pending) 상태에서 시작하여 짧은 생명주기를 통과한다.

보류 프로미스는 미확정(un-settled) 상태로 간주된다.

비동기 연상이 완료되면 이 프로미스는 확정(settled) 상태로 간주 되고 두가지 가능한 상태중 하나가 된다.

  • 성공 (Fulfilled) : 프로미스의 비동기 연산이 성공적으로 완료
  • 실패 (Rejected) : 프로미스의 비동기 연산이 에러나 다른 이유 때문에 성공적으로 완료 되지 않았다.
  1. 대기중(pending) : 결과를 기다리고 있는 상태
  2. 이행됨(fulfilled) : 수행이 정상적으로 끝났고 결과 값을 갖고있는 상태
  3. 거부됨(rejected) : 수행이 비정상적으로 끝난 상태

즉 비동기적으로 작업이 실행되는데
작업이 종료 된후에
실행이 잘 성공했는지 , 혹은 실패했는지 , 성공과 실패 결과값이 무엇인지 반환을 해주는 객체이다.

👉미확정 프로미스 만들기( resolve , reject)

새로운 프로미스는 Promise 생성자를 사용하여 만든다.

이 생성자는 프로미스 초기화 코드를 포함하는 실행자(executor) 함수 하나를 인자로 받는다.

이 실행자에는 resolve()reject() 라 명명된 두 함수가 인자로 전달된다.

  • resolve() : 프로미스의 실행자가 성공적으로 실행 완료
  • reject() : 실행자가 실패했을때
function promise(data) {
  return new Promise((resolve, reject) => {
    return !data ? resject('rejected promise!') : resolve(data);
  })
}

promise();

👉 Promise 를 통한 비동기 제어 방법

프로미스 객체의 결과값은 내부객체이기 때문에 thencatch 로만 접근이 가능하다.

const failurePromise = new Promise(function (resolve, reject) {
  setTimeout(function () {
    reject(new Error("Request is failed"));
  }, 3000);
});

failurePromise
  .then(function (value) { // 거부(실패)된 프로미스는 then 메소드를 통과하고 
    console.log(value);
  })
  .catch(function (error) {
    console.log(error); 
  }); // catch메소드를 실행. error인자가 거부 결과 값임.

failurePromise
  .then((value) => console.log(value))
  .catch((error) => console.log(error)); // 위와 동일한 코드

👉 Promise 제어방법 2

catch

두번째가 실행되지 않는다 ?

파란색의 catch 는 초록색이 정상적으로 동작했는지를 나타내는 promise 에 걸어둔 catch 이다.

마찬가지로 빨간색은 파란색이 정상적으로 동작했는지를 나타내는 promise 에 걸어둔 catch 이다.

그러니 파란색이 정상적으로 출력이 되었을땐 , 빨간색 catch 가 실행이 안된다.

then

then 은 보통 우리가 정상적으로 실행했을때 사용하는 함수이다.

하지만 첫번째 파라미터엔 정상적으로 실행했을때의 return 이 맞지만 ,

두번째 파라미터엔 onrejected 이다.

👉Promise chaining

const promise = new Promise((resolve, reject) => {
  console.log("doing something");
  setTimeout(() => {
    // resolve("test");
    reject(new Error("no network"));
  });
});

promise
  .then((value) => {
    console.log(value);
  })
  .catch((error) => {
    console.log(error);
  });

📌 타입스크립트 return Promise

다들 Promise 를 사용하게 될때 , asyncawait 를 사용한다는것은 알고있을것이다.

나도 처음엔 알고있는 줄 알았다가 다시 공부하고있다

다시 공부하고 이해가 되고나면 쾌감이 쩐다.

너무나도 기분이 좋다. 그래서 다시 한번 이 글을 읽고 정리를 했다.

참고자료

async function getRawValue() {
	return "Raw value";
}

async function getPromiseValue(){
	return( Promise.resolve( "Promise value" ) );
}

// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //

console.log( "Testing Return Values:" );
console.log( "----------------------" );
getRawValue().then( console.log ); // Raw value
getPromiseValue().then( console.log ); // Promise value

이런식으로 말이다.

엇?? 위에는 await 가 없는데여 ?? 왜일까?? 왜 없어도 에러가 나지않고 동작을 하는걸까??

코드를 조금 수정해 볼까 ?

async function getRawValue():Promise<string> {
  let promise = 'test'
  const test = await promise;
  return test;
}

async function getPromiseValue() : Promise<string> {
	return( Promise.resolve( "Promise value" ) );
}

// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //

console.log( "Testing Return Values:" );
console.log( "----------------------" );
getRawValue().then( console.log ); // Raw value
getPromiseValue().then( console.log ); // Promise value

위에 코드와 아래코드의 차이는 무엇일까??
위에 코드에서는 then 을 사용하지 않았다. 대신 await 를 사용하고 있다.
then 대신 await 를 사용해도 되는걸까 ?

참고자료

Promise 이기만 하면 await 기다려서 데이터를 받을 수있기 때문이다.
다만 콜백 함수를 요구하지 않는다는 점에서는 다르다 .
then 에서는 콜백함수를 요구하지만 await 에서는 콜백함수를 요구하지 않는다.

참고자료

promise 이기만 하면 우리는 기다릴(await) 수 있어요.
말 그대로 promise에서 .then() 쓰는거랑 같다.
다만 콜백 함수를 요구하지 않는다는점에서는 다르다.

지금까지는 thenawait 의 차이점과 왜 then 대신 await 로 해도 되는지에 대해서 알아봤고 ,

이제 여기서 return 에 타입을 지정하게 될때 , Promise<string> 로 넣어줘야한다.
그냥 string , object , number 가 아니라 왜 Promise<string> 을 해줘야하는걸까 ??

우리는 항상 왜?? 라는 의문점을 가져야 한다.

우리가 return 값을 받을때 무엇으로 받게 되는가 ??

위의 코드를 다시 볼까 ?

async function getPromiseValue() : Promise<string> {
	return Promise.resolve( "Promise value" );
}
getPromiseValue().then( console.log ); // Promise value

그냥 return 으로 받지않고 , resolve 로 받게된다.

만약 return 타입이 Promise 가 아니라면 ??

이렇게 에러가 발생하게 된다. await 쓰지않고 then 을 쓴다면 ?

역시나 에러 발생

then 에 마우스 hover 를 하게된다면

string 타입은 존재하지 않는다고 나온다.
우리는 string 이란 문자열을 return 할껀데 왜 이러한 일이 발생하는걸까 ?
👇

혹시 위의 그림을 보고 이해가 될까요 ?? 아!!! 하고 생각하시는분이 계실것 같다.

바로 Promise 가 넘어오게 되는것이고 우리는 이것을 return 하는거라서
Promise<string> 으로 return 타입을 지정해줘야한다.

profile
꾸준함이란 ... ?

0개의 댓글