다른 함수(A)의 전달인자로 넘겨주는 함수(B)
function B() {
console.log("called at the back!");
}
function A(Callback) {
callback(); // callback === B
}
A(B);
함수 A는 함수 B(콜백함수)를 동기적으로 또는 비동기적으로 실행할 수 있다.
예) for each, map, filter 메소드 등
[1, 2, 3].map((element, index) => {
return element* element;
});
document.querySelector('#btn').addEventListener('click', (e) => {
console.log('button clicked');
});
콜백함수는 함수 자체를 연결하는 것이지, 함수 실행을 연결하는 것이 아니다.
function handleClick() {
console.log('button clicked');
}
/*함수 자체를 연결하는 옳은 예*/
document.querySelector('#btn').onclick = handleClick; // (o)
document.querySelector('#btn').onclick = () => {handleClick();} // (o)
document.querySelector('#btn').onclick = handleClick.bind(); // (o)
/*함수 실행을 연결하는 잘못된 예*/
document.querySelector('#btn').onclick = handleClick(); // (o)
handleClick(); // handleClick의 실행 결과 === 'undefined'
// return 값이 없기 때문이다.
// 따라서, 마지막 코드는 onclick에 'undefined'를 연결한 것과 마찬가지가 된다.
blocking === 전화
전화를 받으려면 하던 작업을 멈추어야 한다.
요청(착신)에 대한 결과(수신)가 동시에 일어난다.
non-blocking === 문자
요청에 대한 결과가 동시에 일어나지 않는다.
비동기적으로 일어난다.
손님이 아메리카노를 주문한다. === "요청"
"요청"에 blocking이 없다.
"응답"이 비동기적으로 이루어진다.
아메리카노가 완성되면 직원이 손님을 부른다.
완성되면 === "이벤트"
아메리카노가 완성되면 직원이 손님을 부른다.
손님을 부른다 === "이벤트 핸들러" === "콜백함수"
function waitSync(ms){
var start = Date.now();
var now = start;
while(now - start < ms) {
now = Date.now();
}
} // 현재 시각과 시작 시각을 비교하며 ms 범위 내에서 무한 루프를 도는 blocking 함수입니다.
function drink(person, coffee){
console.log(person + '는 '+ coffee + '를 마십니다');
}
function orderCoffeeSync(coffee){
console.log(coffee + '가 접수되었습니다');
waitSync(4000);
return coffee;
}
let customers = [{
name: 'Steve',
request: '카페라떼'
}, {
name: 'John',
request: '아메리카노'
}];
// call synchronously
customers.forEach(function(customer) {
let coffee = orderCoffeeSync(customer.request);
drink(customer.name, coffee);
});
function waitAsync(callback, ms){
setTimeout(callback, ms);
// 특정 시간 이후에 callback함수가 실행되게금 하는 브라우저 내장 긴능입니다.
}
function drink(person, coffee) {
console.log(person + '는 ' + coffee + '를 마십니다');
}
function orderCoffeeSync(coffee) {
console.log(coffee + '가 접수되었습니다');
waitSync(2000);
return coffee;
}
let customers = [{
name: 'Steve',
request: '카페라떼'
}, {
name: 'Jhon',
request: '아메리카노'
}];
function orderCoffeeAsync(menu, callback){
console.log(menu + '가 접수되었습니다');
waitAsync(function() {
callback(menu);
}, 2000);
}
// call asynchronously
customers.forEach(function(customer) {
orderCoffeeAsync(customer.request, function(coffee) {
drink(customer.name, coffee);
});
});
서버에 자원 요청 및 응답
1. fetch API - 서버에 요청하기
2. AJAX(XHR)
'비동기적'이기 때문에, 로딩이 이루어진다고 하지만, 다른 컴포넌트를 조작할 수 있다.
자바스크립트가 돌아가는 원리 === '비동기'
문제점 : 순서를 제어할 수 없다.
const printString = (string) => {
setTimeout( () => {
console.log(string);
},
Math.floor(Math.random() * 100) + 1
)
}
const printAll = () => {
printString("A")
printString("B")
printString("C")
}
printAll(); // what do you expect? Random
비동기의 순서를 제어하기 위해서 필요하다.
const printString = (string, callback) => {
setTimeout( () => {
console.log(string);
callback();
},
Math.floor(Math.random() * 100) + 1
)
}
const printAll = () => {
printString("A", () => {
printString("B", () => {
printString("C", () => {})
})
})
}
printAll(); // now, what do you expect? A, B, C
문제점: callback hell이 일어난다.(복잡해짐)
resolve()와 reject() 명령어를 통해 다음 action으로 넘어가거나, error를 handle할 수 있다.
첫 task가 끝나면 .then()
을 통해 다음 task를 이어서 진행할 수 있다.
콜백함수와 달리, error처리를 하는 경우,
마지막 chain에서만 .catch()
를 통해 error처리를 해줄 수 있다.
const printString = (string) => {
return new Promise((resolve, reject) => {
setTimeout(
() => {
console.log(string);
resolve();
},
Math.floor(Math.random() * 100) + 1
)
})
}
const printAll = () => {
printString("A")
.then(() => {
return printString("B")
})
.then( () => {
return printString("C")
})
}
printAll(); // now, what do you expect?
callback과 동일하게 동작하지만, 가독성을 높여주는 것을 알 수 있다.
문제점: promise hell 발생
function gotoCodestates() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('1. go to codestates') }, 100)
})
}
function sitAndCode() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('2. sit and code') }, 100)
})
}
function eatLunch() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('3. eat lunch') }, 100)
})
}
function goToBed() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('4. goToBed') }, 100)
})
}
gotoCodestates()
.then(data => {
console.log(data);
sitAndCode()
.then(data => {
console.log(data)
eatLunch()
.then(data => {
console.log(data);
goToBed()
.then(data => {
console.log(data)
})
})
})
})
function gotoCodestates() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('1. go to codestates') }, 100)
})
}
function gotoCodestates() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('1. go to codestates') }, 100)
})
}
function sitAndCode() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('2. sit and code') }, 100)
})
}
function eatLunch() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('3. eat lunch') }, 100)
})
}
function goToBed() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('4. goToBed') }, 100)
})
}
gotoCodestates()
.then(data => {
console.log(data);
return sitAndCode()
})
.then(data => {
console.log(data);
return eatLunch();
})
.then(data => {
console.log(data);
return goToBed();
})
.then(data => {
console.log(data);
})
promise화된 함수들에 대하여,
result
를 async
함수로 만들어 주고
await
을 사용하여, 비동기 함수들을 동기 함수처럼 사용할 수 있다.
promise 일종이지만, promise 함수 보다, 훨씬 코드 가독성이 높아진다.
function gotoCodestates() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('1. go to codestates') }, 100)
})
}
function gotoCodestates() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('1. go to codestates') }, 100)
})
}
function sitAndCode() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('2. sit and code') }, 100)
})
}
function eatLunch() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('3. eat lunch') }, 100)
})
}
function goToBed() {
return new Promise((resolve, reject) => {
setTimeout( () => { resolve('4. goToBed') }, 100)
})
}
const result = async() => {
const one = await gotoCodestates();
console.log(one);
const two = await sitAndCode();
console.log(two);
const three = await eatLunch();
console.log(three);
const four = await goToBed();
console.log(four);
}
result();
순회 가능한 객체에 주어진 모든 프로미스가 이행한 후, 혹은 프로미스가 주어지지 않았을 때 이행하는 Promise를 반환한다.
반환 형태는 '배열'
주어진 프로미스 중 하나가 거부하는 경우, 첫 번째로 거절한 프로미스의 이유를 사용해 자신도 거부합니다.