독립적으로 돌아가는 작업을 비동기 작업이라고 한다.
즉, 동시에 여러 가지 작업을 할 수 있는 개념
비동기 작업의 단위를 말한다.
new Promise(...)
생성const promise1 = new Promise((resolve, reject) => {
// 비동기 작업
})
const
로 선언했기 때문에 재할당되지 않는다.new Promise(…)
로 Promise객체 생성resolve
는 executor 내에서 호출할 수 있는 또 다른 함수 = 성공 함수 reject
executor 내에서 호출할 수 있는 또 다른 함수 = 실패 함수new Promise()
는 기다리지 않고 바로 호출해버린다.then
메소드와 catch
로 설정한다.then
메소드는 해당 Promise가 성공했을 때 동작을 지정한다. 인자로 함수를 받는다.
catch
메소드는 해당 Promise가 실패했을 때의 동작을 지정한다. 인자로 함수를 받는다.
const promise1 = new Promise((resolve, reject) => {
resolve(); // 성공시 호출하는 함수 -> then을 호출한다.
});
promise1
.then(() => {
console.log("then!"); // 성공시 호출
})
.catch(() => {
console.log("catch!"); // 실패시 호출
});
new Promise(…)
할 수 없기 때문에 그대로 리턴하는 함수를 만든다.function startAsync(age) { // 재사용하기 위한 함수 생성
return new Promise((resolve, reject) => {
if (age > 20) resolve();
else reject();
});
}
const promise1 = startAsync(25);
promise1
.then(() => {
console.log("1 then!");
})
.catch(() => {
console.log("1 catch!");
});
const promise2 = startAsync(15);
promise2
.then(() => {
console.log("2 then!");
})
.catch(() => {
console.log("2 catch!");
});
resolve
, reject
함수에 인자를 전달함으로써 then
및 catch
함수에서 비동기 작업으로부터 정보를 얻을 수 있다.function startAsync(age) {
return new Promise((resolve, reject) => {
if (age > 20) resolve(`${age} success`);
else reject(new Error(`${age} is not over 20`));
});
}
const promise1 = startAsync(25);
promise1
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error(error);
});
const promise2 = startAsync(15);
promise2
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error(error);
});
function setTimeoutPromise(delay) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, delay);
// setTimeout(resolve, delay); 요약해서 한줄로 작성 가능
});
}
console.log("setTimeoutPromise가 시작됩니다.");
const promise = setTimeoutPromise(1000);
promise.then(() => {
console.log("끝났습니다!");
});
요약하면 아래와 같이 코드를 줄일 수 있다.
function setTimeoutPromise(delay) {
return new Promise((resolve) => setTimeout(resolve, delay));
}
console.log("setTimeoutPromise가 시작됩니다.");
const promise = setTimeoutPromise(1000);
promise.then(() => {
console.log("끝났습니다!");
});
함수를 선언할 때 붙여주는 키워드
new Promise()
를 리턴하는 함수를 async
함수로 변환하기
// 기존
// function startAsync(age) {
// return new Promise((resolve, reject) => {
// if (age > 20) resolve(`${age} success`);
// else reject(new Error(`${age} is not over 20`));
// });
// }
async function startAsync(age) {
if (age > 20) return `${age} success`;
else throw new Error(`${age} is not over 20`);
}
const promise1 = startAsync(25);
promise1
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error(error);
});
const promise2 = startAsync(15);
promise2
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error(error);
});
async
키워드를 붙인다.new Promise()
부분을 없애고 executor
본문 내용만 남긴다.resolve(value)
부분을 return value;
로 변경한다.reject(new Error());
부분을 throw new Error()로 수정한다.async
함수의 리턴 값은 무조건 Promise
이다.
function setTimeoutPromise(delay) {
return new Promise((resolve) => setTimeout(resolve, delay));
}
async function startAsync(age) {
if (age > 20) return `${age} success`;
else throw new Error(`${age} is not over 20`);
}
async function startAsyncJobs() {
await setTimeoutPromise(1000);
const promise1 = startAsync(25);
try {
const value = await promise1;
console.log(value);
} catch (e) {
console.error(e);
}
const promise2 = startAsync(15);
try {
const value = await promise2;
console.log(value);
} catch (e) {
console.error(e);
}
}
startAsyncJobs();
await [[Promise 객체]]
이렇게 사용한다.await
은 Promise 가 완료될 때까지 기다린다. setTimeoutPromise
의 executor
에서 resolve
함수가 호출될 때까지 기다린다. 그 시간동안 startAsyncJobs
의 진행은 멈춰있다.await
은 Promise 가 resolve
한 값을 내놓는다. async 함수 내부에서는 리턴하는 값을 resolve
한 값으로 간주하므로, ${age} success
가 value
로 들어온다는 점을 알 수 있다.Promise
에서 reject
가 발생한다면 예외가 발생한다. 이 예외 처리를 하기 위해 try-catch
구문을 사용했다. reject
로 넘긴 에러(async 함수 내에서는 throw
한 에러)는 catch
절로 넘어갑니다. 이로써 익숙한 에러 처리 흐름으로 진행할 수 있다.await
사용하면 된다.async
와 await
을 쓰면 실제 작업이 끝나는 걸 기다린 다음 다음 코드를 수행한다는 느낌이다.setTimeout
는 async
함수 안에서 await
을 걸 수가 없다.setTimeout
은 무조건 콜백 함수를 인자로 받기 때문에!!!setTimeout
을 감싸는 Promise 를 만들었다.
- 기다리기만 하면 되는 작업을 비동기로 처리할 수 있습니다. 동시에 여러 작업이 진행되어서 비교적 효율적이지만, 흐름 제어는 동기 코드보다 어렵다.
- Promise 를 생성할 때에는
resolve
,reject
함수를 적절히 호출하는 작업을 넣어주고, 이후 생성된 Promise 에 대해then
,catch
메서드를 호출하여 후속 조치를 정해준다.new Promise(…)
는 async 함수로 적절하게 변환할 수 있다.- async 함수 내에서 Promise 에 대해
await
을 걸어서 작업을 기다릴 수 있다.- 스타일은 되도록 일관되게 작성하는 게 좋다. async-await 을 사용하든지,
resolve-reject-then-catch 를 사용한다.- 여러 Promise 를 동시에 기다리려면
Promise.all
를 사용한다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/async_function
https://springfall.cc/article/2022-11/easy-promise-async-await