[JS] Asynchronous : Promise

강원지·2023년 2월 14일
0

자바스크립트 synchronous함 => 호이스팅 이후 작성한 순서에 따라 코드가 실행됨.
asynchronous : 동기적으로 수행되지 않음. 언제 실행될지 몰라.

웹브라우저 동작원리

웹브라우저 : 자바스크립트 실행해주는 엔진.
브라우저는 stack에 javascript의 코드를 쌓아가며 실행함. 한 번에 한 코드만 실행가능
=>single threaded (병렬처리x)
stack 코드에 변수가 포함되어 있다면 Heap에 검색해서 가져다 씀

처리가 오래걸리는 setTimeout, ajax 요청 코드, 이벤트리스너와 같은 코드들은 stack에서 바로 실행되지 않고 대기 상태로 변경됨.
stack이 비었을 때 비로소 대기 상태였던 코드들을 queue에서 하나씩 stack으로 가져와서 처리함.

stack과 queue를 바쁘게 하면 user는 웹사이트가 느리다고 느낌.

javascript는 한 번에 한 줄을 순서대로 처리하는 동기적 언어임.
가끔 비동기적인 처리(setTimeout, ajax 요청 코드, 이벤트리스너)도 가능함.

Promise

class UserStorage {
  loginUser(id, password) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (id === "wonji" && password === "12") resolve(id);
        else reject(new Error("wrong id or password"));
      }, 1000);
    });
  }
  getRoles(id) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (id === "wonji") resolve({ name: "wonji", role: "admin" });
        else reject(new Error("no access"));
      }, 1000);
    });
  }
}
const userStorage = new UserStorage();
const id = prompt("enter your id");
const pw = prompt("enter your pw");
//const id = "wonji";
//const pw = "12";
userStorage
  .loginUser(id, pw)
  .then(userStorage.getRoles)
  //   .catch(console.log) x=>막 줄에서 에러 핸들링
  .then((user) => alert(`Hello ${user.name}, you have a ${user.role} role`))
  .catch(console.log);

producer

const promise = new Promise((resolve, reject) => {
    // 네트워크를 통해 data를 받아오거나 file 에서 뭔가 큰 정보를 받아올때 사용한다 무거운작업
    // 동기방식으로 하면 받아오는시간동안 다른작업을 못하기때문에
    // Promise 를 선언하는순간 콜백함수를 전달
    // 네트워크에서 data 를 가져오는 코드를 작성하면 선언하는그순간 바로수행
    console.log("doing something...");
    setTimeout(() => {
        resolve("ellie");
        // reject(new Error('no network'));
    }, 2000);
});

consumer

promise
    .then((value) => {
        // promise 가 잘 동작했으면 value 라는값을  value = promise.resolve 의 값
  		//promise의 비동기함수에서 resolve('Ellie')에 대응
        console.log(value); // 내가 지정한 동작을 통해 받아올거야
    })//then은 promise를 반환
    .catch((error) => {
        // promise 가 실패하면 error 라는 값을  error = promise.reject
  		//promise의 비동기함수에서 reject(new Error('no network'))에 대응
        console.log(error); // 내가 지정한 동작을 통해 받아오기
    })
    .finally(() => {
        // 성공 실패 여부 상관없이 가장 마지막에 동작. error, then 이후에도 finally가 동작
        console.log("finally"); // 특정 기능을 마지막에 쓰고싶을 때
    });

promise chaining

const fetchNumber = new Promise((resolve, reject) => {
    setTimeout(() => resolve(1), 1000);
});

fetchNumber
    .then((num) => num * 2) //fetchNumber 잘 동작했으면 그 숫자를 2배 곱하고 //2
    .then((num) => num * 3) // 그숫자에 3을 곱한다
//6
    .then((num) => {
        //나온 숫자를
        return new Promise((resolve, reject) => {
            // then 에선 다시 promise (비동기코드) 를 사용해서 값을 받아올수있음
            setTimeout(() => resolve(num - 1), 1000); // 소요시간은 총 2초여야함
        });
  //5
    })
    .then((num) => console.log(num));
//5
//then은 값 전달 또는 promise 전달 가능

에러 핸들링

const getHen = () =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve("🐓"), 1000);
    });
const getEgg = (hen) =>
    new Promise((resolve, reject) => {
        setTimeout(() => reject(new Error(`error! ${hen} => 🥚`)), 1000);
    });
const cook = (egg) =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve(`${egg} => 🍳`), 1000);
    });

getHen() // 닭을 받아오고
    .then(hen=>getEgg(hen)) // 받아온 닭을 통해 egg 를 받아오고
    // .catch((error) => { 계란을 받다가 에러가 생기면 빵을 리턴
    //     return "🍞";
    // })
    .then(egg=>cook(egg) // egg 를 받아오면 후라이를 받아오고 ( 빵을 받아와서 후라이로)
    .then(meal=>console.log(meal)) // 후라이를 받아오면 그걸 출력
          
    //value가 하나라면 생략 가능
getHen() // 닭을 받아오고
    .then(getEgg) 
    // .catch((error) => { 계란을 받다가 에러가 생기면 빵을 리턴
    //     return "🍞";
    // })
    .then(cook) 
    .then(console.log) 
    .catch(console.log);

0개의 댓글