본문 바로가기
JS 공부

JS문법종합반 정리 4주차 - 콜백함수와 제어권, 동기와 비동기, 비동기작업의 동기적 표현

by 나노다 2024. 11. 8.

콜백함수와 제어권

 콜백함수란 다른 코드의 인자로 넘겨주는 함수. 이때 콜백함수의 매개변수, 양식, 실행, 호출 시점 등에 대한 모든 제어권은 얘를 인자로 받는 코드가 가짐!! 사용자가 실행시키고 싶을 때 실행할 수 없음!

 

 

동기와 비동기 개념

  • 동기 synchronous : 현재 실행 중인 코드가 종료돼야만 다음 코드를 실행
  • 비동기 asynchronous : 실행  중인 코드의 완료 여부와 무관하게 즉시 다음 코드로 넘어감

별도의 "요청, 실행 대기, 보류" 등의 기능을 갖는 코드는 모두 비동기적인 코드

 

 

비동기 작업의 동기적 표현

1. Promise 활용

  • Promise는 처리가 끝나면 알려줘~ 하는 약속임.
  • new 연산자로 호출한 Promise의 콜백함수는 바로 실행
  • 콜백함수 내부의 resolve(처리 성공) 또는 reject(처리 실패) 중 하나가 실행되지 전까진 then(다음 처리)이나 catch(오류)로 넘어가지 않음!
/* 예시 */
new Promise(function (resolve) { // new Promise(콜백함수)로 약속 시작
	setTimeout(function () {
		var name = '에스프레소';
		console.log(name);
		resolve(name); // resolve 실행 종료돼야만
	}, 500);
}).then(function (prevName) {  // then 구문 처리 시작!
	return new Promise(function (resolve) {
		setTimeout(function () {
			var name = prevName + ', 아메리카노';
			console.log(name);
			resolve(name);
		}, 500);
	});
})

 

2. Generator 활용

  • 제너레이터 함수는 iterator 객체를 반환함. 보통 function뒤에 별표 *가 붙어있다는 특징이 있음
  • 여러 개의 값을 필요에 따라 하나씩 반환(yield)할 수 있음. 일반 함수에서 return이 제너레이터에선 yield인 느낌 (제너레이터에서 return은 마아지막 반환하고 함수 끝낼 때 씀)
  • next() 메서드를 통해 함수를 실행하면 가장 먼저 만나는 yield의 값을 반환하고, done을 통해 함수 실행이 끝났는지 진행 중인지 알려줌. 근데 반환할 값이 남았는 지 여부로 이해하는 게 쉬운 듯? yield나 return이 남아있으면 done이 되지 않은 거니 false. 싹 다 반환했으면 true
/* 예시 */
var addCoffee = function (prevName, name) {
	setTimeout(function () {
		coffeeMaker.next(prevName ? prevName + ', ' + name : name); 
        // 여기서 매 타이머마다 다음 yield 실행!
	}, 500);
};

var coffeeGenerator = function* () {
	var espresso = yield addCoffee('', '에스프레소');
	console.log(espresso);
	var americano = yield addCoffee(espresso, '아메리카노');
	console.log(americano);
	var mocha = yield addCoffee(americano, '카페모카');
	console.log(mocha);
	var latte = yield addCoffee(mocha, '카페라떼');
	console.log(latte);
};

var coffeeMaker = coffeeGenerator();
coffeeMaker.next(); // 여기서 첫 yield 실행!

 

3. async / await 활용 (+ Promise)

  • async가 붙은 함수의 실행로직에서 await를 만나면, await의 처리가 끝날 때까지 기다리는 원리 
  • 이 때 await와 오는 메서드는 항상 Promise를 반환해야함!
/* 예시 */
var addCoffee = function (name) { // await 마다 실행될 함수
	return new Promise(function (resolve) { // Promise를 반환함!
		setTimeout(function(){
			resolve(name);
		}, 500);
	});
};

var coffeeMaker = async function () { // async가 붙은 함수, 스코프에서 await 만나면 기다림
	var coffeeList = '';
	var _addCoffee = async function (name) { // console.log를 위한 함수 
		coffeeList += (coffeeList ? ', ' : '') + await addCoffee(name);
	};
	await _addCoffee('에스프레소'); // 첫 await
	console.log(coffeeList);
	await _addCoffee('아메리카노'); // 다 될 때까지 기다렸다가 두 번째 await
	console.log(coffeeList);
	await _addCoffee('카페모카'); // 마찬가지
	console.log(coffeeList);
	await _addCoffee('카페라떼'); // 마찬가지
	console.log(coffeeList);
};

coffeeMaker(); // 딸깍 실행