S2 . 과제(Promise, async/await, fetch API)

Haizel·2022년 11월 25일
0

Front-End Developer 되기

목록 보기
30/70
post-thumbnail

Part1. 필기

/*
먼저 promise는 javascript 비동기 처리에 사용되는 객체이다.
promise는 주로 서버에서 받아온 데이터를 화면에 표시할 때 사용한다.
========================================================================
***Q1. Promise 실행 함수의 두 개의 파라미터 resolve 와 reject 는 각각 무엇을 의미하나요?**
**!resolve 와 reject란?**
promise를 통해 new Promise()로 프로미스를 생성한다고 가정하자.
여기서 new Promise에 전달되는 함수는 executor(실행자, 실행 함수) 라고 부른다.
executor은 new Promise가 만들어질 때 자동적으로 실행된다.

executor의 인수 resolve와 reject는 자바스크립트에서 자체 제공하는 콜백이다.
1. resolve(value) — 일이 성공적으로 끝난 경우 그 결과를 나타내는 value와 함께 호출
2. reject(error) — 에러 발생 시 에러 객체를 나타내는 error와 함께 호출

- executor는 상황에 따라 인수로 넘겨준 콜백 중 하나는 반드시 호출해야 한다 
=> 따라서 executor는 romise의 상태를 둘 중 하나로 변화시킨다.

**!정리하자면,**
resolve와 reject는 executor의 인수이며 자바스크립트에서 자체 제공하는 콜백이다. 
resolve는 일이 성공적으로 끝난 경우 그 결과를 나타내는 value와 함께 호출하고,
reject는 에러 발생 시 에러 객체를 나타내는 error와 함께 호출한다.

==============================================================================
**Q2. Promise.prototype.then 메서드와 Promise.prototype.catch 메서드는 무엇을 리턴하나요?
!프로미스 메서드**
1. .then : .then의 인수인 함수를 실행(이행)한다.
- 이행과 실패의 결과(실행결과,에러)를 모두 받을 수 있다.
2. .catch : 에러가 발생한 경우만 다룬다.
- .catch(f) === .then(null,f) 완전히 일치
- 에러처리는 .then(), .catch() 모두 가능하지만 가급적 .catch()로 에러를 처리하는게 더 효율적이다
(catch가 더 많은 예외 처리 사항을 핸들링 할 수 있기 때문이다.)
3. .finally :  성공,실패 여부와 상관 없이 절차를 마무리한다.
.finally(f) ==  .then(f, f) 유사
===========================================================================
**Q3. Promise의 세 가지 상태는 각각 무엇이며, 어떤 의미를 가지나요?
!promise의 3가지 상태**
promise엔 3가지 상태(states)가 있다. 
-> 여기서 상태란, 프로미스의 처리과정을 의미하며, new Promise()로 프로미스를 생성하고 종료될 때까지 3가지 상태를 갖는다.
1. Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태
- new Promise() 메서드를 호출하면 대기(Pending) 상태가 된다.
- new Promise() 메서드를 호출할 때 콜백 함수를 선언할 수 있고, 콜백 함수의 인자로 resolve, reject를 사용할 수 있다. 

2. Fulfilled(이행) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
- 콜백 함수의 인자 resolve를 실행하면 이행(Fulfilled) 상태가 된다.
- 이행 상태가 되면 then()을 이용하여 처리 결과 값을 받을 수 있다.

3. Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태
- 실패한 이유(실패 처리의 결과 값)를 catch()로 받을 수 있다.
======================================================================
**Q4. await 키워드 다음에 등장하는 함수 실행은 어떤 타입을 리턴할 경우에만 의미가 있나요?
     그리고 await 키워드를 사용할 경우, 어떤 값이 리턴되나요?**
참고자료 : https://ko.javascript.info/async-await
**!async와 await**
1. async
async는 function 앞에 위치하고 function 앞에 async를 붙이면 해당 함수는 항상 프라미스를 반환한다.
만약 프라미스가 아닌 값을 반환하더라도 이행 상태의 프라미스(resolved promise)로 값을 감싸 이행된 프라미스가 반환되도록 한다.
=> 즉, async가 붙은 함수는 반드시 프로미스를 반환하고, 프로미스가 아닌 것은 프로미스로 감싸 반환한다. 

2. await
1)await 키워드는 async함수 안에서만 동작한다.
`let value = await promise`
2)자바스크립트는 await 키워드를 만나면 프로미스가 처리될 때까지 기다린다. 그리고 그 후 결과가 반환된다.
3)await 키워드 다음 추가 동작코드가 있을 시, await 키워드가 작성된 코드가 동작하고 그 다음에 다음 순서의 코드가 동작한다.

(*)await 키워드의 장점
1.await 키워드는 프로미스가 처리되길 기다리는 동안 엔진이 다른일을 할 수 있기에 -> CPU 리소스가 낭비되지 않는다.
2.await 키워드를 사용하면 promise.then보다 가독성 좋고 쓰기도 쉽다.
(*)await키워드의 주의점
1. async 함수가 아닌 일반 함수엔 사용할 수 없다(문법에러 발생)
2. await는 최상위 레벨 코드에서 작동하지 않는다.
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json(); //--> 문법에러 발생
-> 하지만 익명 async함수로 감싸면 최상위 레벨 코드에서도 awit를 사용할 수 있다.
(async () => {
    let response = await fetch('/article/promise-chaining/user.json');
    let user = await response.json();
    ...
})();

**!정리하자면,**
*function 앞에 async 키워드를 추가하면(async 키워드의 효과)
1. 함수는 언제나 프로미스를 반환하고 2. 함숭수 안에서 await를 사용할 수 있다.
*프로미스에 await 키워드를 붙이면 프로미스가 처리될 때까지 대기 -> 처리 완료되면 조건에 따라
1. 에러발생(예외가 생성됨) 2. 에러 미발생(프로미스 객체의 result 값을 반환한다)

-> async/await를 사용하면 promise.then/catch가 거의 필요 없다.

*/

Part2.

**//*01. CallBack**
const getDataFromFile = function (filePath, callback) {
    // TODO: fs.readFile을 이용해 작성합니다
    fs.readFile(filePath, "utf-8", (err, data)=>{
        if(err){
            //'에러가 발생할 경우, callback 첫번째 인자에 에러 객체가 전달되어야 합니다'
            callback(err, null);
        }else {
        //'callback 두번째 인자에 파일 내용이 전달되어야 합니다'
        callback(null, data);
        }
        })
    };
    
  //getDataFromFile('README.md', (err, data) => console.log(data));

**//*02. PromiseConstructor**
const getDataFromFilePromise = filePath => {
    // TODO: Promise 및 fs.readFile을 이용해 작성합니다.
  //'Promise 형태로 리턴되어야 합니다'
    return new Promise((resolve, reject)=>{
    fs.readFile(filePath,"utf8", (err, data)=>{
        if(err){
            reject(err)
        }else{
            resolve(data);
          }
        });
      })
    };
    
  //getDataFromFilePromise('README.md').then(data => console.log(data));

**//*03. basicChaining**
// HINT: getDataFromFilePromise(user1Path) 및 getDataFromFilePromise(user2Path)를 이용해 작성합니다
const readAllUsersChaining = () => {
    // TODO: 여러개의 Promise를 then으로 연결하여 작성합니다
    return getDataFromFilePromise(user1Path)
    .then((user1)=> {
        return getDataFromFilePromise(user2Path)
        .then((user2)=>{
            return `[${user1}, ${user2}]`
        });
       })
      .then((text)=> JSON.parse(text));
    };
    
  // readAllUsersChaining();

**//*04.PromiseAll**
const readAllUsers = () => {
    // TODO: Promise.all을 이용해 작성합니다
    return Promise.all([getDataFromFilePromise(user1Path),getDataFromFilePromise(user2Path)])
    .then(([user1, user2])=>{
        return `[${user1}, ${user2}]`
     })
    .then(text => JSON.parse(text));
    }
    
 /* 효근님 코드
 const readAllUsers = () => {
  return Promise.all([getDataFromFilePromise(user1Path),getDataFromFilePromise(user2Path)]
    .then((value)=>{
      return [JSON.parse(value[0]),JSON.parse(value[1])];
       });
      }
    */
    

**/*! Promise.all() 메서드란?**
순회 가능한 객체에 주어진 모든 프로미스가 이행한후, 프로미스를 반환한다.
입력 값으로 들어온 프로미스 중 하나라도 거부 당하면 Promise.all()은 즉시 거부된다.
구문 : promis.all(iterable:배열과 같이 순회 가능한 객체)
*/

**//*05. asyncAwait**
//!async는 함수 앞에 선언
const readAllUsersAsyncAwait = async () => {
        // TODO: async/await 키워드를 이용해 작성합니다
    let user1 = await getDataFromFilePromise(user1Path)
    let user2 = await getDataFromFilePromise(user2Path)
    
    let join = `[${user1}, ${user2}]`
    let result = JSON.parse(join)
    return result;
    }

    // readAllUsersAsyncAwait();
    
    module.exports = {
        readAllUsersAsyncAwait
    }

 //await 키워드로 작성된 코드는 await 키워드가 작성된 코드가 동작하고 -> 그 다음 순서의 코드가 동작한다.

Part3.

**//*01. basicChaining**
function getNewsAndWeather() {
    // TODO: fetch을 이용해 작성합니다
    // TODO: 여러개의 Promise를 then으로 연결하여 작성합니다
  return fetch(newsURL)
  .then(response => response.json())
  .then(news => {
    return fetch(weatherURL)
    .then(response => response.json())
    .then(weather => {
      return {
      /* /data/latest 의 응답 내용과 /data/weather 응답 내용을 합쳐 새로운 객체로 리턴*/
        news : news.data,
        weather : weather
        }
      });
    }) 
  }

**//*02. basicChaining**
function getNewsAndWeatherAll() {
    // TODO: Promise.all을 이용해 작성합니다
  return Promise.all([
    fetch(newsURL),
    fetch(weatherURL)
  ])
    .then (([news, weather])=> {
    return Promise.all([news.json(), weather.json()])
    })
    .then(([news, weather])=>{
    return {
      news : news.data,
      weather : weather
    }
   })
  }

**//*03.asyncAwait**
async function getNewsAndWeatherAsync() {
    // TODO: async/await 키워드를 이용해 작성합니다
  const a = await fetch(newsURL).then(response => response.json())
  const b = await fetch(weatherURL).then(response => response.json())
  
  return {news : a.data, weather : b}
  }
profile
한입 크기로 베어먹는 개발지식 🍰

0개의 댓글