Asynchronous_엘리님 강의 정리
=================================<< Callback >>===================================
//JavaScript is synchronous.
//Execute the code block by orger after hoisting.
//hoisting: var, function declaration
console.log('1');
setTimeout(()=>console.log('2'),1000);
console.log('3');
//Synchronous callback
function printImmediately(print){ // 호이스팅이 되서 코드 젤 상단으로 올라가지만
print();
}
printImmediately(()=>console.log('hello'));// 여기서 불렀으니 여기서 실행됨
//Asychronous callback
function printWithDelay(print, timeout){//setTimeout을 감싸고 있는 함수, 전달받은 인자를 set~에게 전달
setTimeout(print, timeout);
}
printWithDelay(()=> console.log('async callback'), 2000);//콜백함수와 2초를 전달하자
//Callback Hell example
class UserStorage {
loginUser(id, password, onSuccess, onError){
setTimeout(()=>{
if(
(id === 'nara' && password === 'artist') ||
(id === 'enda' && password === 'dreamer')
){
onSuccess(id); //전달받은 onSuccess 라는 콜백을 불러서 id를 전달해준다
}else{
onError(new Error('not found')); // 만약 발견되지 않았으면 onError 콜백을 불러서 Error 오브젝트 만들어서 'not found' 전달해줄거다
}
}, 2000);// 이 코드블럭을 2초뒤에 실행해줘~ 라는 의미,
}
getRoles(user, onSuccess, onError) {
setTimeout(()=> {
if(user === 'nara'){
onSuccess({name: 'nara', role: 'genius'});// 객체 전달
} else {
onError(new Error('no access'));
}
}, 1000)
}
}
// 1. 사용자에게 id, password 입력 받아온다
// 2. 서버에게 로그인
// 3. 로그인한 사용자에게 id받아오고, 다시 roles 요청해 받아온다 :mean 만든 인스턴스의 gerRoles에 다시 접근(인자전달) 밑 참고
// 4. 사용자의 오브젝트를 얻게됨(걔네를 출력)
const iamUser = new UserStorage();
const id = prompt('enter your id');
const password = prompt('ente your password'); // prompt를 변수로 저장해 밑에 인자로 넣어줌으로써 사용자가 입력하는 값을 전달하게끔
iamUser.loginUser(
id,
password,
user => {
iamUser.getRoles(
user,
obj => {
alert(`Hello ${obj.name}, ${obj.role}`)
},
error => {
console.log(error)
}
);
},
error => {
console.log(error)
}
);
//콜백지옥 : 가독성 떨어짐/ 에러발생, 디버깅시 어려움/ 유지보수 어려움
==================================<< Promise >>===================================
// Promise is a JavaScript object for asynchronous operation.
// # State: pending -> fulfilled / rejected (기능을 수행하고 있는 중인지, 성공했는지, 실패했는지)
// # Producer vs Consumer (데이터 제공자와 데이터 소비자)
//promise 안에서 (resolve or seject 호출 안하면 pending 상태됨)
// 1.Producer
// executer의 콜백함수를 만든다-> promise 만드는 순간 executer 콜백함수가 바로 실행됨
const promise = new Promise((resolve,reject) => {
//doing some heavy work(network, read files) -> network, read files 들이 promise 만드는 순간 실행됨 -> but 순서를 정해주고 싶을땐?
// 시간이 걸리는 것들은 비동기적으로 처리하는 것이 좋다.
console.log('doing something...');
setTimeout(()=>{
resolve('nara'); // 성공적으로 받아온 데이터를 resolve라는 콜백함수 통해 전달
reject(new Error('no network')); // Error class: one of JavaScript object
}, 2000);
})
// 2. Consumers: then, catch, finally
promise
.then(value => {
console.log(value); // When you invoke 'then', -> return the same Promise, so 'catch' can use it
})
.catch(error =>{
console.log(error);
})
.finally(()=>{
console.log('finally');
})
// 3. Promise chaining
const fetchNumber = new Promise((resolve,reject)=> {
setTimeout(()=> resolve(1), 1000);
});
fetchNumber
.then(num => num * 2)
.then(num => num * 3)
.then(num => { // # then: 값 바로 전달, 혹은 또 다른 비동기 promise 전달
return new Promise((resolve, reject)=>{ //다른 서버에 보내서 다른 숫자로 변환된 값 받아올거다-> 새로운 promise 리턴
setTimeout(()=> resolve(num-1), 1000);
})
})
.then(num => console.log(num));
// 4. Error Handling
const getHen = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve('🐔'), 1000);
});
const getEgg = hen =>
new Promise((resolve, reject)=> {
setTimeout(() => reject(new Error(`error! ${hen}=> 🥚`)) , 1000); // resolve(`${hen}=> 🥚`)
});
const cook = egg =>
new Promise((resolve, reject)=> {
setTimeout(() => resolve(`${egg} => 🍳`), 1000);
});
getHen()
.then(hen => getEgg(hen)) // 값 받아서 인자로 넘겨줌
//.catch(error =>{return '🥖'}) // 계란을 받아오는데 문제가 있어도 전체 promise 체인에 문제가 생기지 않도록 (cook에 빵전달)
//.catch(console.log) // Error: error! 🐔=> 🥚 at promise.js:55 // undefined => 🍳 at promise.js:67
.then(egg => cook(egg))
//.catch(console.log) ->여기서 잡으면 에러메세지+ 밑 undefined 됨. 아무것도 넘겨주지 않아서?
.then(meal => console.log(meal))
.catch(console.log) // 에러가 밑으로 전달되서 잡혀짐 Error: error! 🐔=> 🥚 at promise.js:55
// .then(getEgg) 콜백함수를 전달할때 받아오는 value를 바로 다음함수에 전달시 생략 가능
// .then(cook)
// .then(console.log);
===============================<< Callback to Promise >>================================
class UserStorage {
loginUser(id, password){
return new Promise ((resolve, reject)=>{
setTimeout(()=>{
if(
(id === 'nara' && password === 'artist') ||
(id === 'enda' && password === 'dreamer')
){
resolve(id);
}else {
reject(new Error('not found'));
}
}, 2000)
})
}
getRoles(user){
return new Promise ((resolve, reject)=>{
setTimeout(()=> {
if(user === 'nara'){
resolve({name: 'nara', role: 'genius'});
} else {
reject(new Error('no access'));
}
}, 1000)
})
}
}
const iamUser = new UserStorage();
const id = prompt('enter your id');
const password = prompt('ente your password');
iamUser.loginUser(id,password)
.then(iamUser.getRoles)
// .then(id =>
// iamUser.getRoles(id) // 전달하는 인자와 받는 인자가 같으면 생략가능
.then(obj => alert( `Hello ${obj.name}, ${obj.role}`))
.catch(console.log);
==================================<< Async >>===================================
// async & await
// clear sytle of using promise :)
// function fetchUser() {
// return new Promise((resolve, reject)=>{
// //do network request in 10 secs...
// resolve('nara');
// });
// }
//########### fetchUser().then(data=> console.log(data)); // 함수로 바로 호출하는 방법
//############ 밑은 변수에 할당해서 호출
// const user = fetchUser(); // fetchUser 라는 것은 결국 promise 리턴, then 콜백함수 이용 유저가 들어오면 console.log출력
// user.then(console.log); // nara
// console.log(user); // Promise {<fulfilled>: "nara"}
//-------------------------------------------
// Promise {<fulfilled>: "nara"}
// __proto__: Promise
// [[PromiseState]]: "fulfilled"
// [[PromiseResult]]: "nara"
// 1. async
async function fetchUser() {
//do network request in 10 secs...
return 'nara';
}
const user = fetchUser();
user.then(console.log);
console.log(user);
// 2. await
// 동기적인 코드 쓰는 것처럼 보임 , 가독성이 좋다
function delay(ms) {
return new Promise (resolve => setTimeout(resolve, ms)) // 정해진 ms가 지나면 resolve 호출
}
async function getApple(){ // 'await' can be used in the function which has 'async' keyword
await delay(1000); // 'await' waits until the delay function finished(?) for 3 seconds,
return '🍎'; // and then makes 'Promise' as it has 'async' keyword, returning apple.
}
async function getBanana(){
await delay(2000);
//throw new Error(`error`);
return '🍌';
}
//###################################### 굳이 프로미스를 쓰는 함수를 만들어보면 ##################################
// function getBanana (){
// return delay(3000) // 바나나 안에서 프로미스 리턴
// .then(()=> '🍌') // 어떤 값을 받던지 결국엔 바나나 리턴하는 함수 만듬
// }
// function pickFruits(){
// return getApple().then(apple => {
// return getBanana().then(banana => `${apple} + ${banana}`); // 받은 인자들을 출력하기 위해..``template? 씀
// })
// }
//############################################### await 사용 ###################################################
// async function pickFruits(){
// const apple = await getApple(); // 저 두 await한 함수들은 서로 연관성 x -> 순차적으로 진행하면 비효율적
// const banana = await getBanana();
//
// return `${apple} + ${banana}`;
// }
//########################################### await - error 처리 #################################################
// async function pickFruits(){
// let apple = null;
// try {
// apple = await getApple();
// } catch (error) {
// console.log(error);
// }
// let banana = null;
// try {
// banana = await getBanana();
// } catch (error) {
// console.log(error);
// }
// return `${apple} + ${banana}`;
// }
async function pickFruits(){ // 위 두 await한 함수들은 서로 연관성 x -> 순차적으로 진행하면 비효율적
const applePromise = getApple(); // promise는 만드는 순간 코드 블럭 실행됨-> 사과와 바나나에 promise 만들어서 병렬적으로 코드 수행됨
const bananaPromise = getBanana(); // 둘다 delay promise에서 값을 받아오니까.. 이렇게 함수를 promise로 저장가능??
const apple = await applePromise;
const banana = await bananaPromise;
return `${apple} + ${banana}`;
}
pickFruits().then(console.log);
// 3. useful APIs
//모든 promise들을 다 받을때까지 병렬적으로 묶어줌-> 배열형태로 전달하면, 그 배열이 전달되고..
function pickAllFruits(){
return Promise.all([getApple(),getBanana()]).then(fruits =>
fruits.join(' + ')
);
}
pickAllFruits().then(console.log);
//배열에 전달하는 promise중 가장 먼저 값 리턴하는 아이만 전달되어짐
function pickOnlyOne() {
return Promise.race([getApple(),getBanana()]);
}
pickOnlyOne().then(console.log);
Author And Source
이 문제에 관하여(Asynchronous_엘리님 강의 정리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@nala723/Promise엘리님-강의-정리저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)