<그냥하자> JavaScript (31) 비동기 프로그래밍

.·2024년 8월 5일

출처 : 인프런 얄팍한 코딩사전

우선 chat한테 비동기 프로그래에 대한 개념을 살짝 물어보니,,,


예를들어 우리가 어느 웹사이트에서 다운로드 할 때 사이트가 얼지 않고 다른걸 클릭이 가능했던 거는 비동기방식으로 구현이 됐다라고 이해를 해도 될거 같다.

setTimeout 함수

전역 setTimeout() 메서드는 만료된 후 함수나 지정한 코드 조각을 한 번 실행하는 타이머를 설정합니다. (출처 MDN)

첫 번째 인자로 넣은 콜백 함수를 두 번째 인자로 넣은 수 만큼의 밀리초 후 실행

Web API, Node.js 등 자바스크립트 환경의 기능 - 언어의 기능이 아님


+++ 09.02 추가

setTimeout(함수, 밀리초);

참고로 타이머의 시간은 정확하지 않다고 한다. 자바스크립트는 기본적으로 한 번에 한 가지 일만 할 수 있기 때문

setTimeout()을 여러번 호출해도 모두 비동기 함수이기에 동기 코드가 모두 실행되고 난 후에 진행된다.

setInterval()

자바스크립트는 자체적으로 반복 기능을 수행하는 setInterval(함수, 밀리초); 함수를 제공한다. 지정한 시간마다 주기적으로 지정한 함수를 실행한다.

clearTimeout() 과 clearInterval()

setTime()과 setInterval() 함수는 웹 페이지를 닫을 때까지 계속 실행되므로 중간에 끄는 방법이 위 함수이다.

const 아이디 = setTime(함수, 밀리초);
clearTimeout(아이디);

const 아이디 = setInterval(함수, 밀리초);
clearInterval(아이디); 

setTimeout()은 비동기 함수이기에 setTimeout()의 콜백 함수보다 아래에 있는 코다가 더 먼저 실행되는 것이다. console.log / clearTimeout()이 먼저 실행되므로 setTimeout()의 콜백함수는 실행되기 전에 취소 된다.


+++ 09.02 추가

호출 스택과 이벤트 루프

호출 스택은 동기 코드를 담당하고, 이벤트 루프는 비동기 코드를 담당한다.
비동기 코드 실행에는 백그라운드와 태스크큐라는 개념도 있다.

백그라운(background)는 타이머를 처리하고 이벤트 리스너를 저장하는 공간.

태스크 큐(task queue) 실행될 콜백 함수들이 대기하고 있는 공간.

태스큐 큐에서 호출 스택으로 함수를 이동시키는 존재가 이벤트 루프.

정리하면 백그라운드에서 코드를 실행하는 것이 아니라 실행될 콜백 함수들을 태스크 큐로 보내면 태스크 큐에는 실행될 콜백 함수들이 대기하고, 먼저 들어온 함수부터 실행되지만 태스크 큐도 함수를 직접 실행하지 않고 이벤트 루프를 통해서 호출 스택으로 함수를 이동시킨다.

호출된 함수의 역순을 보여준다. 그럼 (익명) 함수가 먼저 실행됨을 알 수 있는데 마지막에 넣은 물건이 뺄 때는 가장 먼저 빠지는 구조때문이다. 이를 프로그래밍에서 스택(stack) 이라고 한다.

함수는 호출 스택에 쌓인 역순으로 종료된다. cosole.trace()가 가장 먼저 종료되어 호출 스택에서 빠져나가야 b()의 실행문이 종료된다.


비동기 asynchronous 코드

동기 synchronous 코드와 달리, 코드가 순서대로 실행되지 않음

일반적으로 타임아웃, 네트워크 요청 등 시간이 걸리는 작업에 사용
당장 할 수 있는 것들을 먼저 다 하고, 시간이 걸리는 작업은 뒤로 넘기기

만약 비동기 방식이 없다면 - 데이터를 받아오는 동안 화면이 어는 등 불편함

eg

프로미스

연속적으로 비동기 코드를 써야하는 경우네는 콜백 함수 안에 또 다른 콜백 함수를 넣어야 하는 상황이 발생 하게 된다. 이를 밈으로 콜백지옥이라고 불리기도 한다. 횟수가 많을수록 가독성도 낮아지고 직관성도 떨어지게 되는 것이다.

eg

철수, 영희, 돌준, 정아, 길돈이 치례로 이어달리기는 하는 코드
각 골인시간 기록 - 이전 콜백함수의 결과가 다음 콜백함수로 넘겨져 축적됨
한 주자라도 데드라인(밀리초)을 넘기면 실패 - 주자마다 다른 실패 메시지 출력
완주 실패시 😢 완주 실패 - ${전체 소요시간} 출력
실패든 성공이든 마지막에 - - 경기 종료 - - 출력


위 예시코드 처럼 (보통 시간이 걸리는) 어떤 과정 이후 주어진 동작을 실행할 것이란 약속이 필요하고, 중첩된 비동기 코드를 직관적이고 연속적인 코드로 작성할 수 있도록 하가 위해 프로미스(promise)가 나오게 된다.

+++ 09.02 추가

const <프로미스 객체> = new Promise( (resolve, reject0 => { 
	resolve(); // 프로미스 성공
    // 또는
    reject(); // 프로미스 실패
}); 

<프로미스 객체>.then( <콜백 함수> );
//또는
<프로미스 객체>.catch( <콜백 함수> );

두 메시드도 인수로 콜백 함수를 넣는다. then()의 콜백 함수는 resolve() 함수를 호출할 때 실행되고, catch()의 콜백 함수는 reject() 함수를 호출할 때 실행

생성자 Promise

새로운 약속을 하는 코드
인자로 받는 콜백함수의 첫 번째 인자 resolve ( 이름은 관례 ) - 약속 이행 성공시, 반환할 값 넣어 실행

프로미스 인스턴스 ( 만들어진 약속 ) 의 then 메서드
resolve를 통해 ( 약속대로 ) 반환된 결과를 인자로 하는 콜백 함수를 넣음
또 다른 프로미스를 반환 - 체이닝 가능

일반적으로 내부에 비동기 코드를 사용
시간이 소모되는 비동기 과정 후 ~를 반환하겠다는 약속

생성자 Promise

인자로 받는 콜백함수의 두 번째 인자 reject ( 이름은 관례 ) - 약속 이행 실패시, 반환할 값 넣어 실행
reject가 실행되면 resolve는 무시됨

프로미스 인스턴스의
catch 메서드 : reject를 통해 ( 실패로 인해 ) 반환된 결과를 인자로 하는 콜백 함수를 넣음
finally 메서드 : 성공하든 실패하든 실행할 콜백 함수 - 필요할 때만 사용
then과 더불어 메서드 체이닝으로 사용

eg 10% 이자, 채무자 파산가능성 10%, 5번 빌려주기

릴레이 예제 프로미스로 구현

profile
해야 되는 일이 하고 싶은 일로

0개의 댓글