본문 바로가기
공부/Frontend

비동기 자바스크립트

by 유스베리이 2024. 5. 29.

비동기 프로그램

다른 작업을 처리하고 다시 돌아와서 마무리

JS -> 비동기 프로그래밍이 많이 쓰임, 리퀘스트를 보내고 사용자와 상호작용해야하기 때문에 필요

 

비동기 프로그래밍을 하려면 꼭 알아야 하는 것

 

- 콜백 (CallBack) 

-프로미스 (Promise)

 

파라미터(Parameter) vs 아규먼트(Argument)

function add(x, y) { //x, y 가 Parameter
  return x + y;
}

add(1, 2); // 1,2 가 Argument

 

콜백(CallBack)

 

콜백 ;

어떤 함수의 아규먼트로 전달되는 함수

 

 

 

 

 

 

 

 

 

비동기 함수 (Asynchronous Function) ; 중간에 다른 작업을 처리하다가 다시 돌아와서 마무리 하는 함수 

setTimeout(callback, delay) 함수

  1. setTimeout() 이전에 있는 코드 실행
  2. setTimeout() 함수 실행: delay 만큼 기다리는 타이머를 시작
  3. setTimeout() 이후에 있는 코드 실행
  4. delay가 지나면 callback 실행

 

-> 비동기가 동기보다 더 빨리 완료

 

console.log('1');

setTimeout(() => console.log('2'), 0);

console.log('3');
console.log('4');
console.log('5');
console.log('6');
console.log('7');
console.log('8');
console.log('9');
console.log('10');


//1
//3
//4
//5
//6
//7
//8
//9
//10
//2

 

setTimeout() 함수의 두 번째 파라미터로 0; 이건 콜백을 바로 실행하라는 뜻

-> 비동기 함수의 콜백은, 아무리 빨리 실행돼도 비동기 함수 이후에 있는 코드가 모두 실행된 후에 실행

-> 실행할 콜백이 여러 개일 경우, 동기적으로 실행

 

setInterval() 함수 ; 시간 간격을 두고 콜백을 반복적으로 실행

 

console.log('Start');

const intervalID = setInterval(() => console.log('2초가 지났습니다'), 2000);

// 7초 후에 setInterval() 해제
setTimeout(() => clearInterval(intervalID), 7000);

console.log('End');

//Start
//End
//2초가 지났습니다
//2초가 지났습니다
//2초가 지났습니다

 

clearInterval() 로 setInterval() 해제(멈춤)

 

DOM 의 addEventListener() 함수 ; 웹페이지 요소에 상호작용이 있을 경우 실행할 함수를 등록

const btn = document.querySelector('.my-btn');

btn.addEventListener('click', () => console.log('button clicked!'));

// ...

 

btn에 클릭('click') 이벤트가 발생할 시 () => console.log('button clicked!') 콜백이 실행

 

React의 useEffect() 함수 ; 컴포넌트가 모두 화면에 그려지는 시점에 콜백 실행

function PostList() {
  // ...

  useEffect(() => console.log('render finished!'), []);

  return (
    <div className="post-list">
      <div className="post-item">...</div>
      <div className="post-item">...</div>
      <div className="post-item">...</div>
      ...
    </div>
  );
}

 

-> 콜백을 바로 실행하지 않고 일단 화면을 그리기 때문에 웹 페이지가 더 빨리 로딩되는 것처럼 보이게 할 수 있습니다.

 

Express의 get() 함수 ; 서버 내에서도 리퀘스트에 대한 처리를 비동기 형태로 진행

app.get('/hello', (req, res) => {
  res.send('Success!');
});

// ...

 

콜백 헬(CallBack Hell)

작업을 이어서 하려면 콜백 안에 콜백을 등록해야 할때  콜백을 중첩해서 사용해야 하는 현상

 

-> Promise 등장

 

 

Promise 

- 비동기 작업이 완료되면 값을 알려주는 객체 

- 작업이 완료되면 값을 알려줄 것을 '약속'함

- fetch는 오래 걸려서 일단 Promise 를 돌려주고 나중에 작업이 완료되면 결과값을 Promise에 채워 넣어줌

 

  • Pending: 비동기 작업이 끝나기를 기다릴 때
  • Fulfilled: 비동기 작업이 성공적으로 끝났을 때. 비동기 작업의 성공 결과를 결과값으로 갖게 됨.
  • Rejected: 비동기 작업이 실패했을 때. 비동기 작업에서 발생한 오류를 결과값으로 갖게 됨.

 

Promise를 다루는 방법

1. async  await 문법

await

const result = await Promise;

// 예시
const response = await fetch('https://learn.codeit.kr/api/employees');

await 은 promise 상태가 fulfilled(결과값 리턴), rejected(오류를 throw) 될 때까지 기다림

 

async

// 일반 function
async function printEmployees() {
  const response = await fetch('https://learn.codeit.kr/api/employees');
  const data = await response.json();
  console.log(data);
}

// Arrow function
const printEmployees = async () => {
  const response = await fetch('https://learn.codeit.kr/api/employees');
  const data = await response.json();
  console.log(data);
}

 

async 함수 안에서 await을 마주치면 함수 바깥으로 나가서 나머지 코드를 실행하다가 promise가 fulfilled/rejected 상태가 되면 다시 함수 안으로 돌아와 코드 실행 

 

 

2. .then() 메소드 + 콜백

.then 

 앞선 Promise 객체가 fulfilled 상태가 될 때까지 기다렸다가 fulfilled 상태가 되면 안에 있는 콜백을 실행

앞선 Promise의 결과값을 콜백의 아규먼트로 전달. 앞선 Promise를 기다리는 동안에는 이후에 있는 코드를 실행.

그리고 .then()도 항상 Promise를 리턴.

  • .then()안의 콜백이 Promise를 리턴할 경우 Promise를 그대로 리턴합니다.
  • .then()안의 콜백이 평범한 값을 리턴할 경우 이 값을 결과값으로 가지는 Promise를 리턴합니다.
fetch('https://learn.codeit.kr/api/employees')
  .then((response) => response.json())
  .then((data) => console.log(data));

console.log('Task 2');
console.log('Task 3');



//Task 2
//Task 3
/*[
  {
    id: 1,
    name: 'Jason',
    email: 'jason@codeitmall.kr',
    department: 'engineering'
  },
  ...
]*/

 

 

 

.then vs await 의 try catch finally 메소드

 

Promise.all() 메소드

Promise.all([p1, p2, p3, ...])은 여러 Promise를 동시에 기다릴 때 사용

  • 아규먼트로 전달된 Promise들이 모두 fulfilled 상태-> Promise.all()이 리턴하는 Promise도 fulfilled 상태가 됨. 아규먼트로 전달되는 Promise의 성공 결과값들로 이루어진 배열을 결과값 갖게 됨.
  • 아규먼트로 전달된 Promise 중 하나라도 rejected 상태 -> Promise.all()이 리턴하는 Promise는 rejected 상태가 됨.  rejected된 Promise의 결과값(오류)을 결괏값으로 갖게 됨.