자바스크립트는 원래 기본적으로 동기적 처리를 한다. 즉 위에서 아래로 하나씩 순차적으로 실행을 하게 된다.
비동기 함수들은 바로 실행이 되지 않고 웹브라우저 API를 호출하여 일단 백테이지와 콜배큐에 추가하고 다른 함수들이 다 실행된 후에여 호출 스택에 넣어 실행한다.
비동기 처리를 하면 바로 실행이 되지 않기 때문에 화면이 순간 멈춰 보이기도 하고 처리하는 시간이 오래 걸린다. 하지만, 비동기처리로 코드 실행 순서를 조작할 필요가 있을 때 사용하게 된다.
💡 비동기 코드 실행 순서
- setTimeout은 브라우저가 제공하는 비동기 함수, 시간이 지나면 콜백 함수를 불러옴—> 브라우저 API
- 비동기 처리는 일단 브라우저에게 처리를 맡겨 놓는다.
- 백그라운드 > 테스크 큐 > 호출 스택 > 콘솔
- 지연시간이 다 되어도 호출 스택에 있는 다른 코드들이 먼저 다 실행되어야 비동기 코드 호출 스택으로 이동이 가능
- 백그라운드 > 태스크큐로 가려면 호출 스택에 아무것도 남지 않아야 함
- setTimeout 변별처리 가능 백그라운드에 따로 1초 기다리고 있으니까
함수를 미리 만들어뒀다가 나중에 호출하여 사용하는 함수
(콜백 함수의 예시)
// 예시1
const 버튼 = document.querySelector('.button');
버튼.addEventListener('click',fucntion(){});
//예시2
function 함수하나 (aa){
console.log('hello');
aa('world');
}
함수하나(console.log);
// hello
// world (함수하나() 안에 콘솔로그 안 찍으면 error)
//예시2가 가능한 이유는 아래 코드처럼 표현이 원래 가능함
let taehee = console.log;
taehee('hello world'); // heelo world
function dessert(count, eat, good) {
count < 3 ? eatDessert() : goodDessert();
}
function eatDessert() {
console.log('오늘 먹어야 할 간식을 먹어주세요');
}
function goodDessert() {
console.log('오늘 먹어야할 간식을 모두 먹었습니다');
}
dessert(4, eatDessert, goodDessert);
콜백지옥 발생 (길어지는 체이닝)
loadScript('1.js', function(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('2.js', function(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('3.js', function(error, script) {
if (error) {
handleError(error);
} else {
// 모든 스크립트가 로딩된 후, 실행 흐름이 이어집니다. (*)
}
});
}
})
}
});
콜백함수를 비동기로 처리하는 방법
✔ 기본 문법
const promise = new Promise((resolve, reject) => {
console.log("hello");//executor(제작코드,실행함수)
});
✔ promise에는 3가지 단계가 있다.
- pending: 대기 상태
- fulfilled: 이행 상태 (resolved)
- rejected: 실패 상태
(출처: 알잘딱깔센 JavaScript)
✔ resolve 땐 then, resolve된 값은 then 파라미터로 들어간다.
let p = new Promise(function(resolve, reject) {
resolve('hello world');
}).then(메시지 => {
alert(메시지); //hello world
return 메시지.split(' ')[0] //hello
}).then(메시지 => {
alert(메시지); //hello
return 메시지[0] //h
}).then(메시지 => {
alert(메시지); //h
});
//hello world
//hello
//h
//h
✔ reject면 catch로 바로 실행된다.
✔ resolve로 실행되다가 중간에 throw error를 만나면 중간을 뛰어넘고 catch로 실행
✔ finally는 성공/실패 상관없이 실행
1) promise 단점으로부터 탄생
2) ‘syntatic sugar’
3) promise의 resolved를 반환
4) await와 사용하기
promise.all
을 쓰면 병렬처리Promise.all
으로 비동기처리// 동기처리 //
setTimeout(()=> {
console.log('5초 끝!')
}, 5000);
setTimeout(()=> {
console.log('10초 끝!')
}, 10000);
function cook(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const myCake = async () => {
await cook(3000);
return '케이크';
};
const myCoffee = async () => {
await cook(2000);
return '커피';
};
const myCookie = async () => {
await cook(5000);
return '쿠키';
};
async function asyncProcess() {
const cake = await myCake();
console.log(cake);
const coffee = await myCoffee();
console.log(coffee);
const cookie = await myCookie();
console.log(cookie);
}
asyncProcess();
// 비동기처리 //
setTimeout(()=> {
console.log('5초 끝!')
}, 5000);
setTimeout(()=> {
console.log('10초 끝!')
}, 10000);
function cook(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const myCake = async () => {
await cook(3000);
return '케이크';
};
const myCoffee = async () => {
await cook(2000);
return '커피';
};
const myCookie = async () => {
await cook(5000);
return '쿠키';
};
async function promiseProcess() {
const results = await Promise.all([myCake(), myCoffee(), myCookie()]);
console.log(results);
}
promiseProcess();