Promise(콜백지옥 탈출), async & await

DOYOUNG·2023년 7월 13일
0

javascript

목록 보기
16/17
post-thumbnail

1. Promise

1) 콜백함수를 이용하여 비동기 처리의 결과 핸들링(성공 or 실패)

function isPositive(number, resolve, reject) {
  setTimeout(() => {
    if (typeof number === "number") {
      // 성공 resolve
      resolve(number >= 0 ? "양수" : "음수");
    } else {
      // 실패 reject
      reject("주어진 값은 숫자가 아닙니다.");
    }
  }, 2000);
}

isPositive(
  10,
  (res) => {
    console.log("성공적으로 수행함 : ", res);
  },
  (err) => {
    console.log("실패 하였음 : ", err);
  }
);

1-1) Promise 이용하여 위의 비동기 처리 다시 작성하기

function isPositiveP(number) {
  const executor = (resolve, reject) => {
    // 실행자
    setTimeout(() => {
      if (typeof number === "number") {
        // 성곡 -> resolve
        console.log(number);
        resolve(number >= 0 ? "양수" : "음수");
      } else {
        // 실패 -> reject
        reject("주어진 값이 숫자형 값이 아닙니다");
      }
    }, 2000);
  };

  const asyncTask = new Promise(executor);
  return asyncTask;
}

const res = isPositiveP([]);

res
  .then((res) => {
    console.log("작업성공: ", res);
  })
  .catch((err) => {
    console.log("작업실패: ", err);
  });

2) 콜백지옥이란?

function taskA(a, b, cb) {
  setTimeout(() => {
    const res = a + b;
    cb(res);
  }, 3000);
}

function taskB(a, cb) {
  setTimeout(() => {
    const res = a * 2;
    cb(res);
  }, 1000);
}

function taskC(a, cb) {
  setTimeout(() => {
    const res = a * -1;
    cb(res);
  }, 2000);
}

taskA(3, 4, (a_res) => {
  console.log("task A : ", a_res);
  taskB(a_res, (b_res) => {
    console.log("task B :", b_res);
    taskC(b_res, (c_res) => {
      console.log("task C :", c_res);
    });
  });
});

콜백함수 안에 콜백함수가 계속 들어가면서 반복되는 것을 콜백지옥(=callback hell)이라고 한다.

2-1) 콜백지옥을 벗어나기 위한 Promise

function taskA(a, b) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const res = a + b;
      resolve(res);
    }, 3000);
  });
}

function taskB(a) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const res = a * 2;
      resolve(res);
    }, 1000);
  });
}

function taskC(a) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const res = a * -1;
      resolve(res);
    }, 2000);
  });
}

taskA(5, 1)
  .then((a_res) => {
    console.log("A RESULT :", a_res);
    return taskB(a_res);
  })
  .then((b_res) => {
    console.log("B RESULT :", b_res);
    return taskC(b_res);
  })
  .then((c_res) => {
    console.log("C RESULT :", c_res);
  });

then 체이닝 : then 메서드를 계속 이어 붙이는 것
위와 같이 then 메서드를 사용하여 계속 안으로 들어가는 콜백지옥이 아닌 아래로 이어쓰는 작업이 가능하다.
또한, 이 방식을 사용하면 중간에 다른 작업을 끼워넣기도 가능하다.

const bPromiseResult = taskA(5, 1).then((a_res) => {
  console.log("A RESULT :", a_res);
  return taskB(a_res);
});

console.log("가나다"); // 중간에 다른 작업 가능

bPromiseResult
  .then((b_res) => {
    console.log("B RESULT :", b_res);
    return taskC(b_res);
  })
  .then((c_res) => {
    console.log("C RESULT :", c_res);
  });

2. async & await - 직관적인 비동기처리 코드 작성

1) async

async function helloAsync() {
  return "hello Async";
}

helloAsync().then((res) => {
  console.log(res); // hello Async
});

async라는 값을 붙여준 함수의 return 값은 비동기 작업 객체 Promise의 resolve의 결과값이 된다.
async를 붙이고 return을 하면 Promise를 return하면서 resolve를 실행한것과 같다.
async는 함수 앞에 옵션처럼 붙어서 그 함수가 Promise를 반환하도록 하는 능력이 있다.

2) await

function delay(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function helloAsync() {
  await delay(3000);
  return "hello async";
}

await을 비동기함수 호출 앞에 붙이게 되면 비동기 함수가 마치 동기적 함수처럼 작동한다.
await 키워드가 붙은 함수의 호출은 그 함수의 실행이 끝나기 전까지 그 아래의 코드를 실행하지 않는다. 그래서 동기적 함수처럼 작동한다고 하는것.
await은 aysnc 함수 내에서만 사용 가능하다.

profile
프론트엔드 개발자 첫걸음

0개의 댓글