드림코딩 by 엘라 의 자바스크립트 기초 강의 2

silverj-kim·2021년 1월 2일
0
post-custom-banner

강의 1 포스팅에서 1~10까지 정리했는데 글이 너무 길어진 것 같아서
자바스크립트의 비동기 처리부터는 2번째 포스팅에서 이어서 정리하려고 한다.

11. 비동기 처리 시작 Callback

자바스크립트의 비동기 처리는
1. 콜백 2. 프로미스 3. awiat/async 3가지만 알면 되고
지금은 첫번째 단계 콜백을 먼저 알아볼 것이다.

Synchronous vs Asynchronous, 동기 vs 비동기

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)); 

codepen

콜백 체인의 문제점

  • 가독성이 떨어짐
  • 비즈니스 로직을 한번에 이해하기가 어려움
  • 디버깅하고 문제 분석이 어려움
  • 유지보수가 어려움

12. Promise

비동기를 간편하게 처리할 수 있는 object
Promise is a Javascript object for asynchronous operation

state

pending -> fulfilled or rejected

producer vs consumer

  1. Producer
    새로운 프로미스가 만들어질 때 executor callback은 바로 실행이 된다.
const promise = new Promise((resollve, reject) => {
  //doing some heavy work
  console.log("doing something...");
  setTimeout(() => {
    //resolve("ej");
    //reject(new Error("error"));
  }, 1000);
});
  1. Consumers : then, catch, finally
    then: resolve
    catch: reject
    finally:
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);

참고

13. Javascript async와 await

promise를 좀 더 간결하고 동기적으로 보이게 해주는 syntactic sugur : async/await

  1. async : 함수 앞에 async 키워드를 붙이는 Promise를 return 하게 된다
//Promise
function fetchUser() {
  return new Promise((resolve, reject) => {
    resolve("Silver");
  });
}
//async
async function fetchUser() {
  return "Silver";
}
const user = fetchUser();
user.then(console.log);
  1. await
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); //사과 + 바나나
  1. await 병렬 처리, Promise APIs
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); //가장 먼저 리턴하는 값만 전달됨

드림코딩

profile
Front-end developer
post-custom-banner

0개의 댓글