--> 일반적으로 자바스크립트는 가벼움을 위해 비동기이므로 값의 반환과 상관없이 진행됨
--> 따라서 순차적으로 진행되어야만 하는 특정부분들에서는 동기 처리가 필요함 (외부에서 데이터를 가져온 후 처리하는 부분 등등)
동기
--> 요청과 그 결과가 한 자리에서 동시에 일어남
--> 요청을 하면 시간이 얼마나 걸리든지 결과를 받아야 함
--> A노드와 B노드 사이의 작업 처리 단위를 맞추겠다는 뜻
비동기
--> 요청과 그 결과가 한자리에서 일어나지 않음
--> 요청한 자리에서 결과가 주어지지 않음
--> 노드 사이의 작업 처리 단위를 맞추지 않아도 된다는 뜻
--> 비동기를 동기 방식으로 처리할 때 주로 사용되는 문법
기존의 비동기 처리를 할 떄 발생했던 콜백지옥 해결
--> 비동기를 동기로 만드는 작업을 비동기 처리라고 한다.
isBusHere(function(isBusHereResult) {
isBusStop(isBusHereResult, function(isBusStopResult) {
isDoorOpen(isBusStopResult, function(isDoorOpenResult) {
findWallet(isDoorOpenResult, function(isWalletHere) {
findCard(isWalletHere, function(isCardHere) {
payBusFare(isCardHere, function() {
// 드디어 결제가 성공했네요...
}, failureCallback);
}, failureCallback);
}, failureCallback);
}, failureCallback);
}, failureCallback);
}, failureCallback);
--> 위의 코드처럼 콜백이 끊임 없이 나타나 가독성이 매우 떨어지게 된다.
isBusHere()
.then(function(isBusHereResult) {
return isBusStop(isBusHereResult)
})
.then(function(isBusStopResult) {
return isDoorOpen(isBusStopResult)
})
.then(function(isDoorOpenResult) {
return findWallet(isDoorOpenResult)
})
.then(function(isWalletHere) {
return findCard(isWalletHere)
})
.then(function(isCardHere) {
return payBusFare(isCardHere)
})
.catch(failureCallback);
--> 가독성이 좋아졌음
isBusHere()
.then(isBusHereResult => isBusStop(isBusHereResult))
.then(isBusStopResult => isDoorOpen(isBusStopResult))
.then(isDoorOpenResult => findWallet(isDoorOpenResult))
.then(isWalletHere => findCard(isWalletHere))
.then(isCardHere => payBusFare(isCardHere))
.catch(failureCallback);
--> 가독성이 매우 좋아졌음
const isReady = true;
// 1. Producer
const promise = new Promise((resolve, reject) => {
console.log("Promise is created!");
if (isReady) {
resolve("It's ready");
} else {
reject("Not ready");
}
});
// 2. Consumer
promise
.then(messsage => {
console.log(messsage);
})
.catch(error => {
console.error(error);
})
.finally(() => {
console.log("Done");
});
// Promise is created!
// It's ready
// Done
promise 함수 생성
resolve 함수를 통해 정상 작동되었음을 나타내며, resolve함수의 요소를 promise 함수가 사용될 때 then의 매개변수에 전달
--> 위의 경우 resolve의 요소 "It's ready"를 then의 매개변수 message에 할당하여 then이 실행됨
reject 함수를 통해 문제가 생겼음을 나타내며, reject 함수의 요소를 promise 함수가 사용될 때 catch의 매개변수에 전달
--> 위의 경우, 만약 isReady가 false였을 경우,
reject의 요소 "Not ready"를 catch의 매개변수 error에 할당하여 catch가 실행됨
==> 즉 resolve일 경우 then으로, reject일 경우 catch로 감 finally는 항상 실행
바로 위의 함수 예시
--> 아래와 같이 Promise가 처음 생성되면 promise의 상태는 pending(대기)상태가 됨
const promise = new Promise((resolve, reject) => {});
console.log(promise);
// Promise { <pending> }
--> 아래와 같이 Promise에서 resolve를 실행하면 Fulfilled(이행)상태가 됨
--> Promise가 정상적으로 실행되었을 때 resolve 사용
const promise = new Promise((resolve, reject) => {
resolve();
});
console.log(promise);
// Promise {<fulfilled>: undefined}
--> Promise에서 reject를 실행하면 Rejected(실패)상태가 됨
--> 정상적으로 실행되지 않음 --> 잘못된 것을 알리기 위해 reject 사용
const promise = new Promise((resolve, reject) => {
reject();
});
console.log(promise);
//Promise {: undefined}
Promise를 처음 생성할때 Promise의 내부 코드블럭이 실행됩니다. 이를 executor라 하는데, executor 실행 결과에 따라 resolve 혹은 reject를 불러줍니다.
const isReady = true;
// 1. Producer
const promise = new Promise((resolve, reject) => {
// executor
console.log("Promise is created!");
if (isReady) {
resolve("It's ready");
} else {
reject("Not ready");
}
});
// Promise is created!
Promise의 결과에 따라 후처리를 하는 부분입니다. Promise가 정상적으로 실행되어 resolve가 되었으면 then을 통해 후처리가 가능하고, reject가 될 경우 catch를 통해 후처리가 가능합니다.
const isReady = true;
// 1. Producer
const promise = new Promise((resolve, reject) => {
console.log("Promise is created!");
if (isReady) {
resolve("It's ready");
} else {
reject("Not ready");
}
});
// 2. Consumer
promise
// promise에서 resolve가 될경우
.then(messsage => {
console.log(messsage);
})
// promise에서 reject가 될경우
.catch(error => {
console.error(error);
})
// Promise is created!
// It's ready
--> premise를 더 쉽게 사용하게 해줌
--> 즉 더 쉽게 동기로 만들 수 있음
async function f() {
return 1;
}
--> 함수 앞에 async를 붙이면 항상 프라미스를 반환
--> 프라미스가 아닌 값을 반환하더라도 이행 상태의 프라미스(resolved promise)로 값을 감싸 이행된 프라미스가 반환되도록 만듬
--> 자바스크립트는 await키워드를 만나면 프라미스가 처리 될때까지 기다리고 결과는 그 이후 반환됨
async function f() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000)
});
let result = await promise; // 프라미스가 이행될 때까지 기다림 (*)
console.log(result); // "완료!"
}
f();
--> 일반적으로 자바스크립트는 편의성을 위해 비동기이므로 값의 반환과 상관없이 진행됨
--> 이것을 프라미스를 사용하여 then, catch등을 통해 동기로 만들어 줬던 것
but
--> await를 걸어주는 것으로 프라미스가 값을 반환할 때까지 기다렸다가 값을 반환하면 진행 --> 위의 코드에선 프라미스가 1초 뒤에 값을 반환하므로 1초 뒤에 진행
--> 좀더 손쉽게 동기 처리가 가능해짐
async function showAvatar() {
// JSON 읽기
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
// github 사용자 정보 읽기
let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
let githubUser = await githubResponse.json();
// 아바타 보여주기
let img = document.createElement('img');
img.src = githubUser.avatar_url;
img.className = "promise-avatar-example";
document.body.append(img);
// 3초 대기
await new Promise((resolve, reject) => setTimeout(resolve, 3000));
img.remove();
return githubUser;
}
showAvatar();
--> 데이터를 읽어온 다음(결과가 반환된 다음) 처리해야 되기 떄문에 동기 방식으로 처리할 필요성이 있음
--> async await를 사용하여 결과가 반환될 때까지 기다렸다가 진행되도록 동기 처리
--> promise 보다도 손쉽게 동기 처리가 가능함