엘리스 17일차 화요일 온라인강의 비동기

치즈말랑이·2022년 4월 26일
0

엘리스

목록 보기
18/47
post-thumbnail

00

자바스크립트
현재 실행중인 코드가 종료되기 전에 다음 라인의 코드를 실행할 수 있다.
비동기 작업을 기다리는 동안 메인 스레드에서는 다른 작업을 실행할 수 있다.
Promise나 콜백 함수 호출 시에는 비동기적으로 동작한다.

Promise
Promise API는 비동기 API에 속한다.
Promise를 사용해 비동기 작업의 진행, 성공, 실패 ㅅ상태를 표현할 수 있다.
Promise는 테스크 큐보다 우선순위가 높은 잡 큐를 사용한다.

01

자바스크립트 엔진은 하나의 메인 스레드로 구성된다.
메인 스레드는 코드를 읽어 한줄씩 실행한다.
브라우저 환경에서는 유저 이벤트를 처리하고 화면을 그린다.

동기적 제어 흐름: 현재 실행중인 코드가 종료되기 전까지 다음 줄의 코드 실행 x
분기문, 반복문, 함수 호출 등이 동기적으로 실행
코드의 흐름 = 실제 제어 흐름
싱글 스레드 환경에서 메인스레드를 긴 시간 점유하면 프로그램 멈춤

비동기적 제어 흐름: 현재 실행중인 코드가 종료되기 전에 다음 라인의 코드를 실행
프로미스, 콜백 함수 등은 비동기적
코드 흐름 ≠ 실제 제어 흐름
비동기 작업을 기다리는 동안 메인 스레드는 다른 작업을 처리

이벤트 루프

자바스크립트 엔진은 비동기 처리를 제공하지 않는다.
대신 정해진 함수를 제공하여 활용 -> 이 함수가 API (setTimeout, fetch, ... WEB API)

비동기 코드를 처리하는 모듈은 자바스크립트 엔진 외부에 있다. -> 이벤트 루프, 테스크 큐, 잡 큐
API모듈은 비동기 요청 처리 후 테스크 큐에 콜백함수를 넣고,
자바스크립트 엔진은 콜스택이 비워지면 테스크큐의 콜백 함수를 실행한다.

자바스크립트 엔진은 하나의 메인 스레드로 구성된다.
메인 스레드를 긴 시간 점유하면, 그동안 프로그램은 멈춘다.
메인 스레드는 브라우저 렌더링, 자바스크립트 실행 등의 작업을 하는 스레드이므로, 어떤 작업이 메인 스레드를 긴 시간 동안 점유하면, 작업이 실행되는 동안 프로그램은 멈춘다. 따라서 긴 처리가 필요한 작업은 비동기로 실행되게 로직을 구성하면 좋다.
비동기적 제어 흐름의 경우 현재 실행중인 코드 외에 다른 작업이 실행될 수 있다.
자바스크립트 엔진은 코드를 실행하고 있지만, 비동기 처리에 의한 작업은 자바스크립트 엔진 외부에서 별도로 실행될 수 있다.
비동기 작업이 실행되는 동안 메인 스레드는 코드를 실행하고 브라우저를 렌더링한다.
이벤트 루프는 자바스크립트 엔진 외부에 존재한다.
node.js환경의 경우 libuv라는 모듈에서 비동기 처리를 담당한다.
이벤트 루프는 콜 스택이 비워질때 테스크 큐에서 콜백 함수를 꺼내 콜스택에 넣는다.
비동기 처리가 끝나면 테스크 큐에 콜백 함수가 들어간다.
setTimeout 등의 함수는 비동기 처리를 끝내면 테스크 큐에 콜백 함수를 넣는다. fetch 등의 다른 API 또한 마찬가지.
테스크 큐는 들어온 순서대로 콜백 함수를 내보낸다.
이벤트 루프는 콜스택이 비워졌을때, 테스크큐에서 콜백 함수가 들어온 순서대로 함수를 내보낸다. 단 큐는 여러개가 존재하며 그중 우선순위가 높은 큐(잡큐)에서 나중에 들어온 콜백함수가 실행될 수 있다.

Promise

비동기 API중 하나이다.
테스큐가 아닌 잡 큐(Job queue 혹은 microtask queue)를 사용한다.
잡 큐는 테스크 큐보다 우선순위가 높다.

비동기 작업의 진행, 성공, 실패, 순서 표현 가능

let promise = new Promise((resolve, reject) => {
	if (Math.random() < 0.5) {
    	return reject('실패')
    }
  	resolve(10)
})

promise
	.then(data => {
	console.log('성공: ', data)
})
	.catch(e => {
	console.log('실패: ', e)
})
	.finally(() => {
	console.log('promise종료')
})

new Promise(callback)

  • callback함수는 resolve, reject 두인자를 받는다.
  • Promise가 성공했을때 resolve를 호출하고, 실패했을때 reject를 호출한다.
  • then()메서드에 성공했을때 실행할 콜백함수를 인자로 넘긴다.
  • catch()메서드에 실패했을때 실패할 콜백함수를 인자로 넘긴다.
  • finally()메서드는 성공/실패 여부와 상관없이 모두 실행할 콜백 함수를 인자로 넘긴다.
  • then(callback1, callback2)로 callback1의 자리에 성공, callback2의 자리에 실패 메서드를 인자로 넘길 수 있다.

then/catch 메서드가 또다른 promise를 리턴하여 비동기 코드에 순서를 부여한다
동일한 객체에 메서드 연결 -> 체이닝(chaining)

Promise.all

Promise.all([
	promise1,
  	promise2,
  	promise3
])

	.then(values => {
		console.log("모두 성공:", values)
})
	.catch(e => {
		console.log("하나라도 실패:", e)
})

Promise의 배열을 받아 모두 성공시 각 Promise의 resolved 값을 배열로 반환
하나의 Promise라도 실패시 가장 먼저 실패한 Promise의 실패 이유를 반환한다.

Promise의 콜백은 잡큐를 사용한다.
Promise 객체는 비동기 처리중 상태를 표현할 수 있다. (pending)
Promise를 비동기 처리 순서를 강제할 수 있다.
then() 체인을 통해
finally()메서드는 성공, 실패에 상관없이 항상 호출된다.

function 프로미스함수(n) {
    return new Promise(function(resolve, reject) {
        if (조건) {
            resolve(`${n}`)
        } else {
            reject(`${n}`)
        }
    })

}
profile
공부일기

0개의 댓글