티스토리 뷰
hoisting
var
변수 선언과 함수 선언문에서 발생한다.
함수 내에서 아랫쪽에 존재하는 내용 중 필요한 값들을 최상단으로 끌어올린다.
실제로 코드가 올라가는 것이 아니고, JavaScript
내부적으로 끌어올려서 처리하는 것이다.
따라서 실제 메모리에서의 변화도 없다.
var
의 할당과 함수 표현식은 hoisting
되지 않는다.
var foo; // var의 선언
function foo2() { console.log('hello'); } // 함수 선언문
var foo = 'hello'; // var의 할당
var foo2 = function() { console.log('hello'); } // 함수 표현식
콜백 함수
함수가 끝나고 난 뒤에 인자로 전달되어 실행되는 함수
콜백(setTimeout
)을 이용한 비동기 처리
function printWithDelay(print, timeout) {
setTimeout(print, timeout);
}
printWithDelay(() => console.log('async callback'), 2000);
Promise
를 이용한 비동기 처리
- 상태 - 성공했는지 실패했는지
- producer - consumer의 견해 차이
state : 수행 중일 때 pending
→ fulfilled
or rejected
- producer :
Promise
object
const promise = new Promise((resolve, reject) => {
// doing some heavy work (network, read files)
console.log('doing something...');
setTimeout(() => {
resolve('hello');
}, 2000);
});
새로운 Promise
객체가 생성될 때, executor
는 자동 생성된다.
- consumer :
then
,catch
,finally
promise
.then(value => {
console.log(value);
})
.catch(error => {
console.log(error);
})
.finally(() => {
console.log('finally');
});
then
- 정상일 때 수행
catch
- error 발생 시 수행
finally
- 무조건 수행
Promise
chaining
const fetchNumber = new Promise((resolve, reject) => {
setTimeout(() => resolve(1), 1000);
});
fetchNubmer
.then(num => num * 2)
.then(num => num * 3)
.then(num => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num - 1), 1000);
});
})
then
을 chaining하여 then
에서 반환된 값을 chaining된 다음 then
으로 전달 가능
- Error Handling
const getHen = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve('🐓'), 1000);
});
const getEgg = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${hen} => 🥚`, 1000);
});
const cook = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${egg) => 🍳`, 1000);
});
getHen()
.then(hen => getEgg(hen))
.catch(error => {
return '🍗';
})
.then(egg => cook(egg))
.then(meal => console.log(meal))
.catch(console.log);
// getHen().then(getEgg).then(cook).then(console.log);
// 🐓 => 🥚 => 🍳
chaining
되어 있어도 then
, catch
를 연속으로 연결시키면
성공했을 때는 then
, 실패했을 때는 catch
를 수행하게 된다.
error 발생을 고려하여 항상 error handler(catch
)를 설정해주어야 한다.
async
- await
Promise
객체를 chaining하면 복잡해진다.
깔끔하게 Promise
를 사용하는 방법이 async
- await
이다.
따라서 async
- await
를 이용하여 동기식으로(순서대로) 코드를 작성하지만 비동기로 작동되게 한다.
function fetchUser() {
// do network request in 10 secs....
return 'hello'; // Promise 객체로 반환
}
const user = fetchUser();
console.log(user);
fetchUser()
가 10초 걸리기 때문에 뒤에 나오는 코드들은 10초 후에 실행된다.
따라서 이 문제를 해결하고자 비동기 처리를 해준다.
비동기 처리를 해주기 위해 fetchUser()
이 Promise
객체를 반환하게 바꾼다.
function fetchUser() {
return new Promise((resolve, reject) => {
// do network request in 10 secs....
resolve('hello');
});
}
const user = fetchUser();
user.then(console.log);
console.log(user);
Promise
를 이용하지 않고 간단하게 비동기를 사용하려면 async
사용
async function fetchUser() {
// do network request in 10 secs....
return 'hello'; // Promise 객체로 반환
}
const user = fetchUser();
user.then(console.log);
console.log(user);
await
의 사용
async
함수 안에서 사용한다.
await
이 끝날때까지 기다려준다.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(3000); // 3초 후 아래 코드 실행
return '🍎';
}
async function getBanana() {
await delay(3000);
return '🍌';
}
다음과 같이 Promise
를 많이 chaining하게 되면 콜백 지옥처럼 복잡해진다.
function pickFruits() {
return getApple()
.then(apple => {
return getBanana()
.then(banana => `${apple} + ${banana}`);
});
}
pickFruits().then(console.log);
async
를 활용하여 간단하게 바꿔주면 다음과 같다.
async function pickFruits() {
const apple = await getApple();
const banana = await getBanana();
return `${apple} + ${banana}`;
}
pickFruits().then(console.log);
동기적으로 사용할 수 있고 return
도 자연스러워졌다.
async
- await
에서는 try
- catch
문을 활용하여 error handling을 해준다.
하지만 getApple()
이 끝나고 getBanana()
가 실행되기 때문에 비효율적이다. (이 때, 서로 연관이 없다고 가정)
async function pickFruits() {
const applePromise = getApple(); // 이 때 바로 실행
const bananaPromise = getBanana(); // 이 때 바로 실행
const apple = await applePromise;
const banan = await bananaPromise;
return `${apple} + ${banana}`;
}
pickFruits().then(console.log);
이렇게 하면 await
의 병렬처리가 가능해지지만 이것도 역시 비효율적이다.
그래서 Promise API
인 all()
을 활용해준다.
인자로 들어오는 Promise 객체 배열이 모두 종료된 후 then()
으로 전달된다.
function pickAllFruits() {
return Promise.all([getApple(), getBanana()])
.then(fruits => fruits.join(' + '));
}
pickAllFruits().then(console.log);
race()
는 인자로 들어오는 Promise
객체 배열 중 가장 먼저 종료된 것을 then()
으로 전달해준다.
function pickOnlyOne() {
return Promise.race([getApple(), getBanana()]);
}
pickOnlyOne().then(console.log); // getApple()과 getBanana() 중 먼저 끝나는 것 반환
출처
자바스크립트 11. 비동기 처리의 시작 콜백 이해하기, 콜백 지옥 체험 😱 JavaScript Callback | 프론트엔드 개발자 입문편 (JavaScript ES6)
'JavaScript' 카테고리의 다른 글
[JavaScript] DOM API (0) | 2020.10.11 |
---|---|
[JavaScript] JSON (0) | 2020.10.05 |
[JavaScript] 고차 함수(Higher-Order Function) (1) | 2020.10.01 |
[JavaScript] 1급 시민, 1급 객체 (0) | 2020.09.30 |
- Total
- Today
- Yesterday
- Java
- 인프런
- BFS
- CSS
- 다익스트라
- 알고리즘
- frontend
- 자바스크립트
- MST
- SCSS
- 1급객체
- 웹팩
- js
- javascript
- heapq
- 최소스패닝트리
- 위상정렬
- webpack
- 백준
- BOJ
- 플로이드워셜
- 투포인터
- 에라토스테네스의체
- html
- controller
- 최소공통조상
- springboot
- 고차함수
- 파이썬
- python
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |