하나의 작업이 끝날 때까지 이어지는 작업을 '막는 것'
시작시점과 완료시점이 같은 상황
ex) 커피 주문이 blocking 되지 않고 언제든지 주문을 받을 수 있음
ex) 커피가 완성되는 즉시 커피를 주문하게 되면 1번 손님의 주문완료시점과 2번 손님의 주문 시작시점이 같을 필요가 없음
다른 함수(A)의 전달인자(arguments)로 넘겨주는 함수
- parameter를 넘겨받는 함수A는 callback 함수B를 필요에 따라 즉시 실행(synchronously)할 수도 있고 아니면 나중에 (asynchronously) 실행할 수도 있다
function B() {
console.log('called at the back!');
}
function A(callback) {
callback(); // callback === B
}
A(B);
[1,2,3].map(function(element, index) {
return element * element;
});
document.querySelector('#btn').addEventListener('click', function(e) {
console.log('button clicked');
});
함수 실행을 연결하는 것이 아니라 함수 자체를 연결하는 것임
document.querySelector('#btn').onclick = handleClick; // OK
document.querySelector('#btn').onclick = function() {
handle.Click();
}; // OK
document.querySelector('#btn').onclick = handleClick.bind(); // OK
document.querySelector('#btn').onclick = handleClick();
// NOOOO => 이 경우 함수를 실행시키면 'undefined'가 나옴.
// 함수실행과 연결하는 것이 아니라 함수 자체와 연결하는 것임을 명시하자!!
blocking | non-blocking |
---|---|
전화 | 문자 |
하던 일을 멈추고 받아야함 | 확인 후 나중에 답장 가능 |
요청에 대한 결과가 동시에 일어남 | 요청에 대한 결과가 동시에 일어나지 않음, delay 일어남 |
동기 상태에서는 한가지 작업요청이 실행되기 전까지 client에서 아무것도 못하고 무조건 기다려야하는 상황이 발생하는 반면 비동기 상태에서는 작업요청을 하고 실행되기 전까지 내가 원하는 작업을 진행할 수 있다 => 시간 단축
callback을 통해 async를 제어할 수 있음
const printString = (string) => {
setTimeout(
() => {
console.log(string)
},
Math.floor(Math.random() * 100) + 1
)
}
const printAll = () => {
printString("A")
printString("B")
printString("C")
}
printAll()
// Math.random()함수로 인해 A,B,C 가 순서대로 나오지 않음
const printString = (string, callback) => {
setTimeout(
() => {
console.log(string)
callback()
},
Math.floor(Math.random() * 100) + 1
)
}
const printAll = () => {
printString("A", ()) => {
printString("B", ()) => {
printString("C", () => {})
})
})
}
printAll()
// printString("A", ())에서 콜백함수가 실현되고 그게 실현이 다 되면 B를 부르고 그 다음에 C를 부르고..
// A, B, C 순서대로 진행됨
단점: callback hell => 코드가 너무 늘어나고 지저분해짐
how to deal with callback hell 👿
state: pending -> fulfilled or rejected
성공적으로 받은 데이터는 resolve 콜백함수로 전달함
const promise = new Promise((resolve, reject) => {
console.log('doing someting...');
setTimeout(() => {
resolve('ellie');
// reject(new Error('no network')); // 에러 발생 시
}, 2000);
}),
.then
, .catch
, `finally'promise.then(value => {
console.log(value);
});
// 에러 발생시
//promise.catch(error => {
// console.log(error);
//});
promise.finally(() => {
console.log('finally')'
});
const printString = (string, callback) => {
return new Promise(resolve, reject) => {
setTimeout(
() => {
console.log(string)
resolve()
},
Math.floor(Math.random() * 100) + 1
)
})
}
const printAll = () => {
printString("A")
.then (() => { // A가 다 실행되면 그때 () 콜백함수를 실행시켜라
return printString("B")
})
.then (() => { // B가 다 실행되면 그때 () 콜백함수를 실행시켜라
return printString("C")
})
}
printAll()
// reject인 경우 .catch로 진행됨 (.then 대신에)
// 콜백을 쓸 때 보다 가독성이 좋음
// 동작은 콜백과 동일하게 이뤄짐
const fetchNumber = new Promise((resolve, reject) => {
setTimetout(() => resolve(1), 1000);
});
fetchNumber
.then(num => num * 2) // num <- 1 들어가서 num === 2
.then(num => num * 3) // num === 6
.then(num => { // num === 6
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num - 1), 1000); // 6 - 1
});
})
.then(num => console.log(num)); // num === 5
const getHen = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve('🐓'), 1000);
});
const getEgg = hen =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${hen} => 🥚`), 1000);
// setTimeout(() => reject(new Error(`error! ${hen} => 🥚`), 1000); <=== 에러 발생시
});
const cook = egg =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${egg} => 🍳`), 1000);
});
getHen()
.then(hen => getEgg(hen)) // .then(getEgg)과 동일
// 에러 발생시 아래줄로 대체 가능
// .catch(error => {
// return `🥖`;
// })
.then(egg => cook(egg)) // .then(cook)
.then(meal => console.log(meal)); // .then(console.log)
// 에러 발생시 아래줄 추가
//.catch(console.log)
promise를 좀더 간결하고 동기적으로 실행되게 보이는 것처럼 만들어 줄 수 있음
clear style of using promise
//function fetchUser() {
// return new Promise((resolve, reject) => {
// // do network request in 10 secs...
// resolve('ellie');
// });
//}
async function fetchUser() {
do network request in 10 secs...
return 'ellie';
}
// async라는 키워드를 함수 앞에 쓰기만 하면 됨! promise를 간단하게 쓸 수 있는 syntatic suger :)
const user = fetchUser();
user.then(console.log);
console.log(user);
function delay(ms) {
return new Promise(resolve => set Timeout(resolve, ms));
}
async function getApple() {
await delay (3000); // 3초간 있다가 사과를 리턴
return '🍎';
}
async function getBanana() {
await delay (3000); // 3초 있다가 바나나 리턴
return '🍌';
}
// 콜백지옥의 예시
function pickFruits() {
return getApple()
.then(apple => {
return getBanana().then(banana => `${apple} + ${banana}`);
});
}
//async로 간단하게 만들어주기
async function pickFruits() {
const applePromise = getApple(); // 동시에 병렬적으로 실행시켜줌
const bananaPromise = getBanana(); // "
const apple = await applePromise;
const banana = await bananaPromise;
return `${apple} + ${banana}`;
}
pickFruits().then(console.log)
위에 사과와 바나나를 동시에 병렬적으로 출력하기위한 더 간단한 코드
Promise.all
function pickAllFruits() {
return Promise.all([getApple(), getBanana()]).then(fruits => fruits.join(' + ')
);
}
pickAllFruits().then(console.log)
Promise.race
function pickOnlyOne() {
return Promise.race([getApple(), getBanana()]);
}
pickOnlyOne().then(console.log);
일정 시간 후에 함수를 실행
자바스크립트 내장 비동기 함수
setTimeout(function () {
console.log('1초 후 실행');
}, 1000);
// 123
setTimeout 타이머를 종료
const timer = setTimeout(function () {
console.log('10초 후 실행');
}, 10000);
clearTimeout(timer);
// setTimeout이 종료됨
일정 시간의 간격을 가지고 함수를 반복적으로 실행
setInterval(function () {
console.log('1초마다 실행');
}, 1000);
// 345
setInterval 타이머를 종료
const timer = setInterval(function() {
console.log('1초마다 실행');
}, 1000);
clearInterval(timer);
// setInterval이 종료됨