비동기

dice0314·2023년 5월 16일
0

비동기

  • 이벤트가 독립적으로 발생하는 것
  • 한 작업이 시작되고 끝날 때까지 다른 작업을 수행할 수 없는 동기와 다르게 시작한 작업의 완료를 기다리지 않고 다른 작업도 수행할 수 있다.
  • 작업의 완료 순서는 보장되지 않는다.

비동기 타이머 API

  • 브라우저에서 제공하는 비동기 Web API

1. setTimeout(callback, millisecond)
   - 일정 시간 후 함수 실행

setTimeout(function () {
  console.log('1초 후 실행');
}, 1000); // 1000밀리초(1초)

2. clearTimeout(timerId)
   - 단일 실행 타이머 취소

const timer = setTimeout(function () {
  console.log('10초 후 실행');
}, 10000);
clearTimeout(timer);

3. setInterval(callback, millisecond)
   - 일정 시간의 간격을 가지고 함수를 반복적으로 실행

setInterval(function () {
  console.log('1초마다 실행');
}, 1000);

4. clearInterval(timerId)
   - 반복 실행 타이머 취소

const timer = setInterval(function () {
  console.log('1초마다 실행');
}, 1000);
clearInterval(timer);

callback함수를 이용한 비동기

function delayed(val, callback) {
  setTimeout(function() {
    callback(val);
  }, 2000); // 2초 후에 작업이 완료되면 콜백 함수 호출
}

console.log("1");
delayed("2", function(el) { // delayed 함수로 출력을 지연시켜 3이 먼저 출력된다.
  console.log(el);
});
console.log("3");

출력 결과

1
3
2

callback hell

  • 콜백 함수를 중첩해서 사용하여 코드가 복잡하고 가독성이 떨어지는 상황
data1(function(result1) {
  data2(result1, function(result2) {
    data3(result2, function(result3) {
      // ...
    });
  });
});

Promise

  • 비동기 작업을 처리하기 위한 객체이다.
  • callback함수의 callback hell 문제를 방지할 수 있다.
  • 하지만 Promise도 hell문제가 발생할 수 있다.
  • 아래코드의 경우 then메서드를 사용하여 메서드 안에서 다음 실행될 Promise를 반환하는 방식인데 여러번 중첩될 경우 마찬가지로 hell문제가 발생한다.

Promise의 세가지 상태

  • async/await도 같은 상태를 가진다.

1. 대기(pending)

  • Promise 객체가 생성되었지만 아직 처리되지 않은 초기 상태
  • 비동기 작업이 진행 중일 때의 대기 상태

2. 이행(fulfilled)

  • 비동기 작업이 성공적으로 완료되어 Promise가 이행된 상태
  • 이행된 Promise는 결과 값을 가지며, 값을 반환한다.

3. 거부(rejected)

  • 비동기 작업이 실패하여 Promise가 거부된 상태
  • 거부된 Promise는 오류 정보를 가지며, 오류를 반환한다.

Promise를 이용하여 callback hell을 처리한 코드

const data1 = () => {
  return new Promise((resolve, reject) => {
    // 비동기 작업 수행
    // 성공한 경우 resolve(result1) 호출
    // 실패한 경우 reject(error) 호출
  });
};

const data2 = (result1) => {
  return new Promise((resolve, reject) => {
    // 비동기 작업 수행
    // 성공한 경우 resolve(result2) 호출
    // 실패한 경우 reject(error) 호출
  });
};

const data3 = (result2) => {
  return new Promise((resolve, reject) => {
    // 비동기 작업 수행
    // 성공한 경우 resolve(result3) 호출
    // 실패한 경우 reject(error) 호출
  });
};

data1()
  .then((result1) => {
    return data2(result1);
  })
  .then((result2) => {
    return data3(result2);
  })
  .then((result3) => {
    // 결과 처리
  })
//.then 메서드가 늘어나면 promise hell문제가 될수 있다.
  .catch((error) => {
    // 에러 처리
  });

Promise의 메서드

1. then

  • Promise의 이행상태나 거부상태를 처리한다.
  • then()는 Promise 객체를 반환하므로 메서드 체이닝을 통해 여러 개의 then()을 연결할 수 있다.
const promise = new Promise((resolve, reject) => {
  resolve("성공");
});

promise.then((result) => {
  console.log(result); // "성공"
}).catch((error) => {
  console.error(error);
});

2. catch

  • Promise가 거부된 상태를 처리한다.
  • then()의 두 번째 인자로 전달하는 것과 동일한 역할을 한다.
  • catch()는 Promise 체인 내에서 오류를 처리하는 데 사용한다.
const promise = new Promise((resolve, reject) => {
  reject(new Error("거부"));
});

promise.catch((error) => {
  console.error(error); // 거부
});

3. finally

  • Promise의 이행상태나 거부상태를 처리한다.
  • finally()는 상태에 상관없이 항상 실행되는 코드를 작성할 때 사용한다.
  • Promise 체인 내의 마지막에 위치한다.
  • 다른 then() 이나catch() 뒤에 사용될 수도 있다.
const promise = new Promise((resolve, reject) => {
  resolve("성공");
});

promise.finally(() => {
  console.log("마지막에 실행");
}).then((result) => {
  console.log(result); // "성공"
});

실행 결과

성공
마지막에 실행

4. Promise.resolve

  • 주어진 값을 성공적으로 이행된 Promise로 감싸서 반환한다.
const promise = Promise.resolve("성공");

promise.then((result) => {
  console.log(result); // "성공"
});

5. Promise.reject

  • 할당된 변수의 이유로 거부된 Promise를 반환한다.
const promise = Promise.reject(new Error("거부"));

promise.catch((error) => {
  console.log(error); // Error: 거부
});

6. Promise.all

  • 여러 개의 Promise를 동시에 처리하고, 모든 Promise가 이행될 때까지 기다린 후, 모든 Promise의 결과값을 배열로 반환한다.
  • 동시 처리 하면서 출력 순서가 상관이 없을 경우 사용한다.
  • 하나의 Promise라도 거부되면 모든 Promise는 거부된다.
const promise1 = Promise.resolve("Promise 1");
const promise2 = Promise.resolve("Promise 2");
const promise3 = Promise.resolve("Promise 3");

Promise.all([promise1, promise2, promise3])
  .then((results) => {
    console.log(results); // ["Promise 1", "Promise 2", "Promise 3"]
  });

async/await

  • Promise의 단점을 보완하기 위해 도입된 기능
  • async 키워드로 함수를 선언하고, 비동기 작업 코드 앞에 await 키워드를 사용하여 해당 코드의 작업이 완료될 때까지 기다릴 수 있다.
  • 비동기 코드를 동기 코드처럼 작성할 수 있다.
  • 오류 처리는 try-catch 문을 사용하여 처리할 수 있다.
const data1 = () => {
  return new Promise((resolve, reject) => {
    // 비동기 작업 수행
    // 성공한 경우 resolve(result1) 호출
    // 실패한 경우 reject(error) 호출
  });
};

const data2 = (result1) => {
  return new Promise((resolve, reject) => {
    // 비동기 작업 수행
    // 성공한 경우 resolve(result2) 호출
    // 실패한 경우 reject(error) 호출
  });
};

const data3 = (result2) => {
  return new Promise((resolve, reject) => {
    // 비동기 작업 수행
    // 성공한 경우 resolve(result3) 호출
    // 실패한 경우 reject(error) 호출
  });
};

async function processData() {
  try {
    const result1 = await data1();
    const result2 = await data2(result1);
    const result3 = await data3(result2);
    // 결과 처리
  } catch (error) {
    // 에러 처리
  }
}

processData();
profile
정리노트

0개의 댓글