
자바스크립트는 싱글 스레드를 가지며, 이는 단 하나의 실행 컨텍스트 스택(Call Stack)을 가진다는 말과 일맥상통한다.
※ 싱글 스레드(Single Thread): 한 번에 하나의 테스크만 실행 가능
↪ 처리에 시간이 걸리는 테스크를 실행하는 경우 블로킹(작업 중단)이 발생함.

// ex1.
let a = 0;
// setTimeout(비동기 함수)
setTimeout(function () {
a = 100; // 할당 안됨
console.log('1st');
setTimeout(function () {
console.log('2nd');
setTimeout(function () {
console.log('3rd');
// render('rendering...');
}, 1000);
}, 2000);
}, 3000);
console.log('HELLO');
console.log(a);
// 출력
// HELLO
// 0
// 1st
// 2nd
// 3rd
// setTimeout 함수는 생성된 타이머를 식별할 수 있는 고유한 타이머 id를 반환
// 비동기 함수인 setTimeout 함수는 콜백 함수의 처리 결과를 외부로 반환하거나 상위 스코프의 변수에 할당하지 못한다.
: 비동기를 간단하게 처리할 수 있도록 도와주는 "객체"
resolve(성공), reject(실패))를 인수로 전달받음"미래의 어떤 시점에 결과를 제공하겠다는 약속을 반환"
※ 유의사항
: Promise를 생성하게 되면 excutor(콜백함수)가 바로 실행됨
// ex1(Promise).
const render = () => console.log('rendering...');
const timeout = (time) => (resolve, reject) => {
setTimeout(() => resolve('promise: '), time);
};
const delay = (time) => new Promise(timeout(time));
delay(3000)
.then((msg) => {
console.log(msg + '1st');
return delay(2000);
})
.then((msg) => {
console.log(msg + '2nd');
return delay(1000);
})
.then((msg) => {
console.log(msg + '3nd');
render();
});
// 출력
// promise: 1st
// promise: 2nd
// promise: 3rd
// rendering...
ex. 데이터를 불러오는 경우
사이트의 데이터를 전부 불러올 때 까지 기다리게 된다면 사용자들은 불편함을 느낌
const response = fetch(`myImage.png`) const blob = response.blob(); // display your image blob in the UI somehow
- 이미지를 불러오고 불러온 것을 확인한 후에 응답을 처리하게 해야 함
- 이미지가 불러와지기 전에 응답을 출력하게하면 오류가 뜸
1) pending(대기): 초기 상태
2) fulfilled(이행): 성공적으로 완료된 상태
3) rejected(실패): 실패 상태
4) settled: 비동기 처리가 수행된 상태
// ex2. Promise chainning
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
// reject('error');
}, 1000);
});
promise.then(
// 정상적으로 작동 시 then 메서드에서 반환값 처리
function (result) {
console.log(result)
}
).catch(
// 실패하게되면 catch 메서드에서 오류를 잡음
function (error) {
console.log(error)
}
).finally(() => {
console.log("성공이든 실패든 무조건 실행")
});
// 출력
// ok
// 성공이든 실패든 무조건 실행
// ex3.
const getApple = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve('🍎'), 1000);
});
const getBanana = (apple) =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${apple} -> 🍌`), 1000);
});
const getTrain = (banana) =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${banana} -> 🚆`), 1000);
});
// getApple()
// .then((banana) => getBanana(banana))
// .then((train) => getTrain(train))
// .then((result) => console.log(result));
// 전달하는게 하나일 경우 줄여서 사용가능
getApple()
.then(getBanana)
.then(getTrain)
.then(console.log);
// 출력
// 🍎 -> 🍌 -> 🚆
// ex4. 에러처리를 이용하여 결과 변경
const getApple = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve('🍎'), 1000);
});
const getBanana = (apple) =>
new Promise((resolve, reject) => {
setTimeout(() => reject(new Error(`${apple} -> 🍌`)), 1000);
});
const getTrain = (banana) =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${banana} -> 🚆`), 1000);
});
getApple()
.then(getBanana)
.catch((error) => {
return '🍍';
})
.then(getTrain)
.then(console.log);
// 출력
// 🍍 -> 🚆
프로미스를 요소로 갖는 배열 등의 이터러블을 인수로 전달받음
fulfilled 상태가 되는 것을 기다렸다가 처리 결과를 배열에 저장해 새로운 프로미스를 반환※ 특징
① 순서대로 실행되지만, 앞의 함수를 기다리지 않는다.
② 처리 순서가 보장된다.
⑤ 에러가 나면 그 즉시 에러를 반환한다.
↪ 조건 중 하나라도 누락되면 페이지를 보여주면 안될 때 사용가능
// ex5. Promise.all (가장 긴 task 기준)
function timer(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(time);
}, time);
});
}
console.time('all');
Promise.all([timer(1000), timer(2000), timer(3000)]).then((result) => {
console.log('result', result);
console.timeEnd('all');
});
fulfilled 된 프로미스의 처리 결과를 resolve하는 새로운 프로미스를 반환// ex6. Promise.race (가장 짧은 task 기준)
function timer(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(time);
}, time);
});
}
console.time('race');
Promise.race([timer(1000), timer(2000), timer(3000)]).then((result) => {
console.log('result', result);
console.timeEnd('race');
정리
- 배열에 있는 모든 promise가 트리거가 된다.(약간의 차이 있음)
- Promise.all : 마지막 기준
- Promise.race : 처음 기준