ES5+(callback / promise / async & await)

JIY00N·2023년 4월 1일
0

HTML / CSS / JavaScript

목록 보기
16/18
post-thumbnail

2023.04.01

1. callback

  1. 동기와 비동기
    ✔ Javascript is synchronous 동기
    -> 호이스팅이 된 이후부터 코드의 순서에 따라 실행
    ✔ hoisting: var, funciton declaration등이 젤 위로 올라가는 것
// asynchronous(비동기) 예시
console.log('1');
setTimeout(() => console.log('2'),1000); // 콜백 함수
console.log('3');
// 1 3 2
// Synchronous callback
function printImmediately(print){
	print();
}
printImmediately(()=>console.log('hello')); // 1 3 hello 2
// Asynchronous callback
function printWithDelay(print, timeout){
	setTimeout(print,timeout);
}
printWithDelay(()=>console.log('async callback'),2000); 
// 1 3 hello 2 async callback
  1. callback hell example
class UserStorage{
  loginUser(id,password,onSuccess,onError){
    setTimeout(()=>{
      if ((id === "yoon" && password ==="min")|| (id === "angela" && password ==="lucy")){
        onSuccess(id);
      }else{
        onError(new Error('not found'));
      }
    },2000);
  }
  getRoles(user, onSuccess, onError){
    setTimeout(()=>{
      if (user==="yoon"){
        onSuccess({name:"yoon", role: "admin"});
      }else{
        onError(new Error('no access'));
      }
    },1000);
  }
}
// 1. 사용자에게 id, pw 입력받아옴
// 2. login
// 3. roles
// 4. object 출력
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)=>{
      	alert(`hello ${userWithRole.name}, you have a ${userWithRole.role} role`);
      }, 
      (error)=>{console.log(error)});
  },
  (error)=>{console.log(error)}
);

✔ 콜백 체인의 문제점

  1. 가독성이 떨어진다
  2. 유지보수가 어렵다

2. promise

✔ 비동기를 간편하게 처리할 수 있게 해주는 javascript object
✔ 정해진 장시간의 기능을 수행하고 나서 정상적으로 기능이 수행된다면 성공의 메시지와 함께 처리된 결과값을 전달, 문제 발생하면 에러 발생
1. state: pending -> fulfilled or rejected
2. producer vs consumer

  1. Producer 제공자
// promise를 만드는 순간 콜백함수 내용 바로 실행
// when new Promise is created, the executor runs automatically!!!!
const promise = new Promise((resolve, reject)=>{
 // doing some heavy work(network, read files)
  console.log("doing something..."); // doing something...
  setTimeout(()=>{
    resolve("yoon"); // 성공시
    reject(new Error("no network")); // 실패시
  },2000);
});
  1. Consumer 사용자
// then, catch, finally를 통해 값을 받아옴
// value에는 성공시 yoon이 들어옴
// then: promise가 정상적으로 잘 수행이 되어서 마지막으로 resolve함수를 통해 전달한 값을 value의 pararmeter로 전달
// catch: error 발생시 어떻게 처리할 것인지
// finally: 성공과 실패 여부와 상관없이 마지막에 무조건 호출
promise
  .then((value)=>{
  console.log(value);  // yoon
}) 
  .catch((error)=>{
  console.log(error); // Error: no network
})
  .finally(()=>{
  console.log("finally"); // finally
});
  1. Promise chaining
// then: 값 또는 promise 전달
const fetchNumber = new Promise((resolve, reject)=>{
  setTimeout(()=>resolve(1),1000); // 1 전달
})
fetchNumber
.then(num=>num*2) // 2
.then(num=>num*3) // 6
.then(num=>{
  return new Promise((resolve,reject)=>{
    setTimeout(()=>resolve(num-1),1000); // 5
  });
})
.then(num=>console.log(num)); // 5, 2초 소모
  1. 오류 잘 처리 하기
  1. callback to promise
class UserStorage{
  loginUser(id,password){
    return new Promise((resolve, reject)=>{
       setTimeout(()=>{
      if ((id === "yoon" && password ==="min")|| (id === "angela" && password ==="lucy")){
        resolve(id);
      }else{
        reject(new Error('not found'));
      }
    },2000);
    });
  }
  getRoles(user){
    return new Promise((resolve, reject)=>{
      setTimeout(()=>{
        if (user==="yoon"){
          resolve({name:"yoon", 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(user => alert(`hello ${user.name}, you have a ${user.role} role`)) // 성공했을 경우
  .catch(console.log); // 실패했을 경우

3. async & await

✔ syntactic sugar
✔ clear style to using promise

  1. async
// async를 쓰면 코드 블럭 안이 자동으로 promise로 변경됨
async function fetchUser(){
  // do network request in 10secs...
  resolve("yoon");
}
const user = fetchUser();
console.log(user);
  1. await
    ✔ async 함수 안에서만 사용 가능
function delay(ms){
  return new Promise(resolve=>setTimeout(resolve,ms));
}
async function getApple(){
  await delay(1000); // delay(1초)가 끝날때까지 기다려준다
  throw "error";
  return "apple";
}
async function getBanana(){
  await delay(2000);
  return "banana";
}
async function pickFruits(){
  // 병렬적으로 실행하기
  const applePromise = getApple();
  const bananaPromise = getBanana();
  const apple = await applePromise;
  const banana = await bananaPromise;
  return `${apple} + ${banana}`;
}
pickFruits().then(console.log); // apple + banana
  1. useful Promise APIs
// 1. Promise.all
// promise에 배열을 전달하게 되면 모든 promise들이 병렬적으로 다 받을 때 까지 모음
function pickAllFruits(){
  return Promise.all([getApple(),getBanana()])
  .then(fruits=>fruits.join(" + "); 
}
pickAllFruits().then(console.log); // apple + banana
// 2. Promise.race
// promise에 전달된 배열 중에서 가장 먼저 return된 것 전달
function pickOnlyOne(){
  return Promise.race([getApple(),getBanana()]); 
}
pickOnlyOne().then(console.log); // apple
profile
블로그 이전 했습니다. https://yoon-log.vercel.app/

0개의 댓글