[JavaScript] 비동기

jungmin Lee·2023년 7월 12일
0

Promise

Promise는 Promise객체를 생성하는 함수로, 비동기 작업을 처리하기 위해 사용된다. 주로 서버에서 받아온 데이터를 화면에 표시할 때 사용한다. new Promise()는 Promise 객체를 생성하며, resolve와 reject라는 콜백 함수를 인수로 받는다. 콜백 함수는 비동기 작업이 성공 또는 실패했을 때 호출된다. resolve, reject함수는 정의하지 않아도 자바스크립트 엔진에서 미리 정의하므로 전달 안해도 호출에 문제는 없다.

resolve와 reject 함수

  • resolve: 비동기 작업이 성공적으로 완료되었을때 호출되는 함수이며, Promise를 성공상태로 만든다. resolve 함수에는 작업의 결과나 성공에 대한 정보를 전달할 수 있다. .then을 통해 성공한 정보를 받을 수 있다.
  • reject: 비동기 작업이 실패했을 때 호출되는 함수이며, Promise를 실패상태로 만든다. reject 함수에는 작업 실패에 대한 원인이나 에러 객체 등을 전달할 수 있다. .catch를 통해 실패한 정보를 받을 수 있다.

Promise 인스턴스의 then, catch, finally 메소드

  • Promise.prototype.then() - 성공시 처리
    then 메소드는 Promise 객체가 성공적으로 해결됐을 때 호출되며, 두 개의 콜백 함수를 인수로 받는다. 첫 번째 콜백 함수는 resolve 함수가 호출됐을 때 실행되며, Promise가 반환하는 값을 받는다. 두 번째 콜백 함수는 reject 함수가 호출되거나 예외상황이 발생되었을때 실행된다.
    then 메소드는 체이닝으로 여러 개의 비동기 작업을 처리할 수 있다.

  • Promise.prototype.catch() - 실패시 처리
    catch 메소드는 Promise 체인에서 에러가 있을때 호출된다. reject 함수가 호출되거나 예외가 발생했을 때 실행되며, 에러처리를 하는데 사용된다다. then 메소드처럼 체이닝하여 여러 개의 catch 블록을 사용할 수 있다.

  • Promise.prototype.finally() - 모두 실행
    finally 메소드는 Promise 체인의 마지막에서 성공이나 실패 여부에 상관없이 항상 실행되며, 주로 정리 작업에 사용된다. finally 메소드는 then 또는 catch 뒤에 체이닝하여 사용할 수 있다.

Promise의 세 가지 상태

  • pending(대기) - new Promise() 메서드를 호출하면 대기상태 보류하지도, 받지도 않은 초기 상태. 비동기 처리 로직이 아직 완료되지 않은 상태
  • fullified(이행) : 성공적으로 완료되었습니다. 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태 여기서 콜백 함수의 인자 resolve를 실행하면 이행상태가 되며 then()을 이용하여 처리 결과 값을 받을 수 있습니다.
  • rejected(거절) : 실패함, 오류. 비동기 처리가 실패하거나 오류가 발생한 상태reject를 호출하면 실패상태, 실패 상태가 되면 실패 처리의 결과 값을 catch()로 받을 수 있다.

const renderBlobImage = () => {
  return new Promise((resolve, reject) => {
    const canvas = document.createElement('canvas');
    canvas.width = 300;
    canvas.height = 300;
    
    const ctx = canvas.getContext('2d');
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, (Math.PI / 180) * 360);
    ctx.fillStyle = "orange";
    ctx.fill();
    ctx.closePath();

    canvas.toBlob((blob) => {
      if (blob) {
        const imageUrl = URL.createObjectURL(blob);
        resolve(imageUrl);
      } else {
        reject(new Error('Blob creation failed'));
      }
    }, 'image/png');
  });
};

renderBlobImage()
  .then((imageUrl) => {
    console.log('이미지 생성에 성공했습니다.', imageUrl);
  })
  .catch((error) => {
    console.error('이미지 생성에 실패했습니다.', error);
  });

new Promise를 이용하여 비동기 작업으로 이미지 url을 만들어 내보내는 함수이다. Promise가 성공시에는 reslove 함수로 imageUrl을 내보내어 받을 수 있으며 실패시에는 reject에 error 메세지를 확인할 수 있다. renderBlobImage함수를 호출하여 then을 통해 imageUrl을 받을 수 있으며 catch를 통해 실패시에는 오류메세지를 보여줄 수 있다.



async/await

Async/Await는 Promise를 기반으로 한 비동기 처리이다. Async 함수 내에서 Await 키워드를 사용하여 비동기 작업의 완료를 기다릴 수 있으며, Async 함수는 항상 Promise를 반환하며, 비동기 함수가 리턴하는 Promise로부터 결과값을 추출한다. async를 붙이면 해당 함수는 항상 Promise를 반환하며 Promise가 아닌 것은 Promise로 감싸서 반환한다. Promise가 처리되면 그 결과와 함께 실행이 재개되므로, Promise를 기다리는 동안에는 엔진이 다른 스크립트를 실행이나 이벤트 처리 등을 실행할 수 있어서 CPU 리소스가 낭비되는 것을 막을 수 있다.

await는 .then이 구현되어있으면서 프라미스가 아닌 객체를 받으면, 내장 함수 resolve와 reject를 인수로 제공하는 메서드인 .then을 호출합니다(일반 Promise executor가 하는 일과 동일합니다). 그리고 나서 await는 resolve와 reject 중 하나가 호출되길 기다렸다가((*)로 표시한 줄) 호출 결과를 가지고 다음 일을 진행합니다.

promise.then처럼 await에도 thenable 객체(then 메서드가 있는 호출 가능한 객체)를 사용할 수 있음

async/await와 promise.then/catch
async/await을 사용하면 await가 대기를 처리해주기 때문에 .then이 거의 필요하지 않습니다. 여기에 더하여 .catch 대신 일반 try..catch를 사용할 수 있다는 장점도 생깁니다. 항상 그러한 것은 아니지만, promise.then을 사용하는 것보다 async/await를 사용하는 것이 대개는 더 편리합니다.

그런데 문법 제약 때문에 async함수 바깥의 최상위 레벨 코드에선 await를 사용할 수 없습니다. 그렇기 때문에 관행처럼 .then/catch를 추가해 최종 결과나 처리되지 못한 에러를 다룹니다.

=>await는 promise.then보다 가독성 좋고 쓰기도 쉽습니다.

json parse -> string 타입을 object로 변환

json stringify -> object 타입을 string 타입으로 변환

Promise와 Callback은 비동기 작업을 처리한다.

Callback은 함수를 인자로 전달하여 비동기 작업이 완료 후 호출된다.
Callback은 비동기 작업의 결과를 처리하기 위해 중첩된 함수 형태로 작성되는 경우가 많아 Callback Hall이 발생하여 가독성이 떨어지며 코드의 복잡성이 증가할 수 있다.
Callback Hall현상을 방지하기 위해 Promise가 사용되기 시작했다.

Promise는 ES6에서 도입되었고 class이므로 new 키워드를 통해 Promise 객체를 생성한다.
Promise는 비동기 처리를 수행할 콜백 함수를 인수로 전달받는데 콜백 함수는 resolve, reject 함수를 인수로 전달받는다. Promise 객체가 생성되면 콜백함수는 자동으로 실행되고 코드가 정상적으로 처리되면 resolve함수를 호출하고 에러가 발생하면 reject 함수를 호출하면 된다. new Promise가 반환하는 Promise 객체는 state, result 내부 프로퍼티를 가지고 있으며 .then, .catch, .finally의 메서드를 사용해서 접근이 가능하다.
state는 기본 상태인 pending(대기), 비동기 처리를 수행할 콜백함수가 성공적으로 작동하면 fulfilled(이행)로 변경되고, 에러발생시 rejected(거부)가 된다.
result는 처음에는 undefined이며 비동기 처리를 수행할 콜백함수가 성공적으로 작동하면 resolve(value)가 호출되면 value로, 에러가 발생하면 reject(error)가 호출되고 error로 변한다.
Promise

async와 await는 JavaScript에서 비동기 코드를 작성하는데 사용되며 Promise를 기반으로 한 비동기 작업을 더 편하게 다룰 수 있다.
async는 함수 선언 앞에 사용되며 해당 함수가 비동기적으로 동작함을 나타내며 Promise를 반환하게 된다. await는 async 함수 내부에서 사용되며 Promise가 완료될 때까지 함수의 실행을 기다리며 Promise가 처리되면 결과를 반환하고 함수가 실행이 재개된다.
async와 await를 함께 사용하면 비동기 코드를 순차적으로 작성하고 읽기 쉽게 만들 수 있다.

profile
Leejungmin

0개의 댓글