기술면접_JavaScript_10
프론트엔드 개발자 입문 | JSON Contents JSON파일이란? 파일변환 드림코딩 유투브 채널의 J...
 Callback
 Callbacksynchronous
console.log("1st");
console.log("2nd");
console.log("3rd");
//출력결과: 1st,2nd,3rd
asynchronous
console.log("1st");
setTimeout(()=>{
  console.log("2nd");
  },1000)
console.log("3rd");
//출력결과: 1st,3rd,2nd
//위 코드는 동기언이인 JavaScript를 비동기적으로 처리한 것
다른 함수에 매개변수로 넘겨준 함수로, 넘겨받은 함수는 때가 되면 나중에 호출
//setTimeout은 콜백함수로 실행되며 지금 당장 실행되지 않고 필요한 때에 callback(호출)하여 사용
setTimeout(function(){
  console.log('1초 후 실행되는 코드')
}, 1000) 
//콜백함수는 anonymous로 Arrow function을 통해 표기가능
setTimeout(() => console.log('1초 후 실행되는 코드'), 1000)
정의 : 콜백함수를 반복사용하여 코드의 들여쓰기 수준이 감당하기 힘들 정도로 깊어지는 현상. 여기서 반복사용은 하나의 콜백함수 안에서 계속해서 콜백을 반복하는 것을 말함.
문제 : 코드의 가독성이 떨어지며 오류 디버깅이 어려움 
class UserStorage {
  //사용자 데이터를 서버에서 받아오는 코드
  loginUser(id, password, onSucess, onError) {
    setTimeout(() => {
      if (
        (id === 'ellie' && password == 'dream') ||
        (id === 'coder' && password == 'academy')
      ) {
        onSucess(id);
      } else {
        onError(new Erorr('not found'));
      }
    }, 2000);
  }
  //사용자의 역할(ex.손님,정회원)을 서버에서 받아오는 코드
  getRoles(user, onSucess, onError){
    setTimeout(() => {
      if (user === 'ellie') {
        onSucess({ name: 'ellie', role: 'admin' });
      } else {
        onError(new Error('no access'));
      }
    }, 1000);
  }
}
  /*---------------------------------------------------------*/
  const userStorage = new UserStorage(); //userStorage class delaration
  const id = prompt('enter your id');
  const password = prompt('enter your password');
  //userStorage 사용하여 로그인
  userStorage.loginUser( 
    id, 
    password, 
    user => { //1st Callback
      userStorage.getRoles(
        user,
        userWithRole => { //2nd Callback
          alert(
            `Hello ${userWithRole.name}, you have a ${userWithRole.role} role`
          );
        },
        error => { //3rd Callback
          console.log(error);
        }
      );
    },
    error => { //4th Callback
      console.log(error);
    }
);
 Promise
 PromisePromise State
프로세스가 기능을 수행중인지 혹은 수행을 성공(실패)하였는지에 대한 상태
Producer vs Consumer
producer : 데이터 제공자 (원하는 기능을 수행하여 해당하는 데이터 생성)
const promise = new Promise((resolve, reject) => {
  // doing some heavy work(ex.서버에서 데이터를 받아오는 등의 작업을 말하며, 이를 동기적으로 실행할 경우 비효율적이므로 Promise를 사용하여 비동기적으로 실행하도록 함)
  console.log('doing something...');
  //1. Wizaed of Oz: 실제 서버를 이용하는 것과 같은 효과를 주기위해 setTimeout사용
  //2. resolve or reject사용
  serTimeout(() => {
    resolve('ellie') //기능수행에 성공할 경우 출력
  },2000);
  setTimeout(() => {
    reject(new Error('no network')) //기능수행에 실패할 경우 출력
  },2000);
});
consumer : 데이터 사용자 (원하는 데이터 소비)
promise
  //then: 성공할 경우, value(resolve에서 정의)에서 값을 받아와 출력
  .then((value) => {
    console.log(value);
  })
  //catch: 실패할 경우, 오류메세지 출력
  .catch(error => {
    console.log(error);
  })
  //finally: 성공,실패 여부와 무관하게 출력
  .finally(() => {
    console.log('finally');
  })
Promise chaining
It allows you to chain on another then call which will run when the second promise is fulfilled
const fetchNumber = new Promise((resolve, reject) => {
  setTimeout(() => resolve(1), 1000);
});
fetchNumber
  .then(num => num * 2)
  .then(num => console.log(num));
Promise chaining error handling
//Producer
const gethen = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve('hen'), 1000)
})
const getEgg = hen =>
  new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error (`error! ${hen} -> egg`)), 1000)
})
const cook = egg =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve(`${egg} -> fired egg`), 1000)
})
//Consumer
gethen()
  .then(getEgg)
  .catch(error => {
    return 'alternate';
  })
  .then(egg => cook(egg))
  .then(meal => console.log(meal))
  .catch(console.log);
class UserStorage {
  loginUser(id, password) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (
          (id === 'ellie' && password == 'dream') ||
          (id === 'coder' && password == 'academy')
        ) {
            resolve(id);
        } else {
            reject(new Erorr('not found'));
        }
      }, 2000);
    });
  }
  getRoles(user){
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (user === 'ellie') {
          resolve({ name: 'ellie', 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) //userStorage에 id,pw전달
  .then(userStorage.getRoles) //loginUser에서 resolve일 경우, user를 받아와서 getRoles호출
  //위 코드의 경우, user= > 생략: 콜백함수 전달 시, 받아오는 value를 통해 다른함수를 바로 호출하는 경우, 생략가능
  .then(user => alert(`Hello ${user.name}, you have a ${user.role} role`))
  .catch(console.log);
/*1. async*/
//사용자의 데이터를 받아오는 코드(동기처리): 데이터가 받아와지는 동안 다른 코드를 실행할 수 없음
function fetchUser() {
  return 'ellie'; 
}
const user = fetchUser();
console.log(user);
//사용자의 데이터를 받아오는 코드(비동기처리_async): async를 function앞에 작성하면 자동으로 블럭이 Promise로 변경됨
async function fetchUser() {
  return 'ellie'; 
}
const user = fetchUser();
console.log(user);
/*2. await*/ 
//await사용 시, delay를 통해 비동기처리를 동기처리 코드와 같이 작성할 수 있음
function delay(ms){
  return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
  await delay(1000)
  return 'apple';
}
async function getBanana() {
  await delay(1000)
  return 'banana';
}
async function pickFruits() {
  const apple = await getApple();
  const banana = await getBanana();
  return `${apple} + ${banana}`
}
pickFruits().then(console.log);
/*3. await의 직렬처리 문제*/ 
//아래 코드를 예시로 보았을 때, getApple과 getBanana function이 순차적으로 진행됨 (사과와 바나나는 서로 연관이 없으므로 이를 순차적으로 실행하는 것은 비효율적)
function delay(ms){
  return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
  await delay(1000)
  return 'apple';
}
async function getBanana() {
  await delay(1000)
  return 'banana';
}
//1번 방법(Promise사용): Promise는 생성과 동시에 실행됨으로 getApple과 getBanana를 병렬처리 할 수 있음
async function pickFruits() {
  const applePromise = getApple(); 
  const bananaPromise = getBanana(); 
  const apple = await applePromise;
  const banana = await bananaPromise;
  return `${apple} + ${banana}`
}
//2번 방법(Promise all APIs사용): Promise배열 전달 시, 모든 Promise가 병렬적으로 다 받아질 때 까지 모아줌
function pickFruits() {
  return Promise.all([getApple(), getBanana()]) //Promise가 전부 받아지면
  .then(fruits => fruits.join(' + ')); //배열의 값을 join()을 통해 string으로 병합
}
pickFruits().then(console.log);
//Appendix
function pickOnlyOne() {
  return Promise.race([getApple(), getBanana()]); //race: 배열에 전달 된 Promise중, 가장 먼저 값이 들어온 것만 return
}
Avenco comes with a built-in contact form.
 
      