동기와 비동기[callback, promise, async/await]
동기와 비동기
자바스크립트는 동기적 언어이다.
Hoisting 된 이후부터 우리가 작성한 순서에 따라 동기적으로 실행된다.
(Hoisting : 변수, 함수 선언이 자동으로 위로 올라가는 것)
동기 -> 순서대로 실행
비동기 -> 코드가 언제 실행될지 예측할 수 없음
Synchronous callback //즉각적 동기적으로
function printImmediately (print) {
print();
}
Asynchronous callback //언제 실행될지 모르는
function printWithDelay (print, timeout) {
setTimeout(print, timeout);
}
printWithDelay (() ⇒ console.log(’async callback’), 2000); //2초뒤 실행
Callback
콜백 함수란 어떤 이벤트가 발생한 후, 수행될 함수를 의미합니다.
const getThreePromise = () => new Promise((resolve, reject) => {
resolve(3);
});
//콜백함수 예시
getThreePromise.then((result) => console.log('result :', result));
비동기 프로그래밍을 하면, 어떤 함수가 실행될 때 특정 시점에 콜백함수가 수행될 것입니다.
콜백함수는 자신이 포함된 함수의 환경에 접근이 가능합니다.
클로저는 함수가 선언될 때의 환경을 기억하고 있으므로, 콜백함수는 클로저라고 할 수 있습니다.
여기서 클로저는 이미 생명 주기가 끝난 외부 함수의 변수를 참조하는 함수를 클로저라고 합니다.
Promise
-
State[기능 수행 중인지, 성공, 실패] pending -> fulfilled or rejected
- 자바스크립트에서 비동기를 간편하게 할 수 있게 해주는 Promise
- 비동기를 처리할 때 콜백함수 대신 유용하게 사용할 수 있다.
- 시간이 걸리는 큰 파일을 읽어오는 일들은 비동기로 처리 해야 한다.
- 동기로 읽어오면 읽어오는 동안 다른 코드를 읽지 못한다.
[Producer] //해당하는 데이터를 만들어 내는
//새로운 프로미스가 만들어질 때 executor 가 자동으로 실행된다.
const promise = new Promise((resolve, reject) ⇒ {
//doing some heavy work(network, read files)
console.log('doing something...');
setTimeout(() => {
reslove('ellie'); //성공
reject(new Error('no network')) //실패
},2000);
)};
[Cousumers : then, catch, finally ] //원하는데이터를 소비
promise
.then((value) => {. //then은 promise가 값이 정상적으로 잘 수행이 된다면
console.log(value); //ellie promise 안에서 reslove로 값이 잘 전달 되어 value에 들어온다.
})
.catch(error => {. //체이닝
console.log(error); //Error: no network
})
.finally(() => {
console.log('finally'); //실패와 성공 상관없이 마지막에 호출
});
//3. Promise chaining
const fecthNumber = new Promise((reslove, reject ) => {
setTimeout(() => resolve(1), 1000);
});
fecthNumber. //then 은 값과 다른 promise를 전달 할 수 있다.
.then(num => num*2). //1*2
.then(num => num*3). //2*3
.then (num=> {. //6
return new Promise ((resolve, reject( => {
setTimeout(() => resolve(num-1),1000); //6-1
});
})
.then(num => console.log(num)); //5
Promise 의 then, catch를 사용하다보면 콜백지옥에 빠진다.
async/await
promise를 대신해서 async / await를 사용할 수 있다.
사용법
async function willGetThree() {
return 3;
}
async function main() {
const three1 = await willGetThree();
console.log(three1);
// 3
}
const nameObj = { 0: "Alpha", 1: "Beta", 2: "Chalie" };
const ageObj = { 0: 24, 1: 32, 2: 27 };
const genderObj = { 0: "Male", 1: "Female", 2: "Male" };
function getName(id) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(nameObj[id]);
}, 4200);
});
}
function getAge(id) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(ageObj[id]);
}, 2700);
});
}
function getGender(id) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(genderObj[id]);
}, 5600);
});
}
--------------------------------------------------------- promise를 이용한 선언
async function main() {
const startTime = new Date();
const id = 1; // 0 ~ 2 내에서 자유롭게 바꾸세요!
let name, age, gender; // get함수들을 써서 해당 변수에 값을 담아주세요!
// 첫번째 수행시간 스크린샷. await 를 차례대로 썼을 때,
name = await getName(id);
age = await getAge(id);
gender = await getGender(id);
//await를 사용하면 여러가지 일을 한번에 진행할 수 있음에도 불구하고 차례대로 결과를 받아와
//실행 시간이 15초 정도 걸리게 된다.
// 따라서 아래와 같이 Promise.all을 사용한다.
----------------------------------------------------------------------------
// 두번째 수행시간 스크린샷. Promise.all 을 썼을 때,
const result = await Promise.all([getName(id), getAge(id), getGender(id)]);
//Promise.all을 사용하면 수행시간이 5초대로 낮아진다.
const endTime = new Date();
console.log(`수행시간: ${(endTime - startTime) / 1000}s`);
console.log(result);
}
댓글남기기