강의 1 포스팅에서 1~10까지 정리했는데 글이 너무 길어진 것 같아서
자바스크립트의 비동기 처리부터는 2번째 포스팅에서 이어서 정리하려고 한다.
자바스크립트의 비동기 처리는
1. 콜백 2. 프로미스 3. awiat/async 3가지만 알면 되고
지금은 첫번째 단계 콜백을 먼저 알아볼 것이다.
Javascript is synchronous. 자바스크립트는 동기적이다.
Sync : Execure the code block by order after hoisting.
hoisting: var, function delaration 자동적으로 제일 위로 올라가는 것.
console.log(1);
setTimeout(function() {
console.log(2);
}, 1000);
console.log(3);
위 예제에서 setTimeout에 파라미터로 전달하는 함수는 바로 실행하는 것이 아니라 1초 후 실행하는 콜백(Callback) 함수이다.
Synchronous callback
function printImmediately(print) {
print();
}
printImmediately(() => console.log("hello"));
Asynchronous callback
function printWithDelay(print, timeout) {
setTimeout(print, timeout);
}
printWithDelay(() => console.log("bye"), 2000);`
Callback Hell example
class UserStorage {
loginUser(id, password, onSuccess, onError) {
setTimeout(() => {
if(id === "ej" && password === "dream") {
onSuccess(id);
} else {
onError(new Error("not found"));
}
}, 2000)
}
getRoles(user, onSuccess, onError) {
setTimeout(() => {
if(user === "ej") {
onSuccess({name: user, role: "admin"})
} else {
onError(new Error("no access"))
}
}, 1000)
}
}
const userStorage = new UserStorage();
const id = prompt("enter your id");
const password = prompt("enter your password");
userStorage.loginUser(id, password, (user) => {
userStorage.getRoles(user, (userWithRole) => console.log(`Hello ${userWithRole.name}, you have a ${userWithRole.role}`), (error) => console.log(error));
}, error => console.log(error));
비동기를 간편하게 처리할 수 있는 object
Promise is a Javascript object for asynchronous operation
pending -> fulfilled or rejected
const promise = new Promise((resollve, reject) => {
//doing some heavy work
console.log("doing something...");
setTimeout(() => {
//resolve("ej");
//reject(new Error("error"));
}, 1000);
});
promise
.then((value) => {
console.log(value);
})
.catch((err) => {
console.log(err);
})
.finally(() => {
console.log("finally");
});
Promise chaining
const fetchNumber = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
}, 1000);
});
fetchNumber
.then(num => num*2) //2
.then(num => num*3) //6
.then(num => {
return new Promise((res, rej) => {
setTimeout(() => resolve(num-1), 1000); //5
});
})
.then(num => console.log(num)); //5
Error Handling
const getHen = () => new Promise((res, rej) => {
setTimeout(() => reject(new Error("닭")), 1000);
});
const getEgg = (hen) => new Promise((res, rej) => {
setTimeout(() => resolve(hen + " => egg"), 1000);
});
const cook = (egg) => new Promise((res, rej) => {
setTimeout(() => resolve(egg + " => 계란후라이"), 1000);
});
getHen()
.then(hen => getEgg(hen)) // then(getEgg)
.catch(err => "빵")
.then(egg => cook(egg)) // then(cook)
.then(meal => console.log(meal)); // then(console.log)
.catch(console.log);
Callback hell refactoring
class UserStorage {
loginUser(id, password) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if(id === "ej" && password === "dream") {
resolve(id);
} else {
reject(new Error("not found"));
}
}, 2000)
});
}
getRoles(user) {
return new Promise((res, reject) => {
setTimeout(() => {
if(user === "ej") {
res({name: user, role: "admin"})
} else {
reject(new Error("no access"))
}
}, 1000)
});
}
}
const userStorage = new UserStorage();
const id = prompt("enter your id");
const password = prompt("enter your password");
userStorage.loginUser(id, password)
.then(userStorage.getRoles)
.then((userWithRole) => {
console.log(`Hello ${userWithRole.name}, you have a ${userWithRole.role}`)
})
.catch(console.log);
promise를 좀 더 간결하고 동기적으로 보이게 해주는 syntactic sugur : async/await
//Promise
function fetchUser() {
return new Promise((resolve, reject) => {
resolve("Silver");
});
}
//async
async function fetchUser() {
return "Silver";
}
const user = fetchUser();
user.then(console.log);
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(3000);
return "사과";
}
async function getBanana() {
await delay(3000);
return "바나나";
}
async function pickFruits() {
//return getApple().then(apple => {
// return getBanana().then(banana => `${apple} + ${banana}`);
//});
const appel = await getApple();
const banana = await getBanana();
return `${apple} + ${banana}`;
}
pickFruits().then(console.log); //사과 + 바나나
async function pickAllFruits() {
return Promise.all([getApple(), getBanana()])
.then(fruits => fruits.join(" + "));
}
pickAllFruits().then(console.log); //병렬처리
function pickOnlyOne() {
return Promise.race([getApple(), getBanana()]);
}
pickOnlyOne().then(console.log); //가장 먼저 리턴하는 값만 전달됨