본문 바로가기
패스트캠퍼스/수업내용정리

2019-05-31 프로미스,

by sunnykim91 2019. 5. 31.

Ajax를 위해 이해해야하는 것들

  • Client - Sever
  • HTTP
  • JSON
  • 비동기

둘다 기본적으로 한개를 고치는 것. 하나안에 id content complte가 있고

PUT - id를 제외한 전부 다 고치면

PATCH  - 여기서 content나 complete를 고치면

 

 

Ajax를 이용한 실습

<!DOCTYPE html>
<html lang="en">
</head>
<body>
  <pre class="result"></pre>
  <script>
    const $result = document.querySelector('.result');
    
    const render = content => ( $result.innerHTML = JSON.stringify(content, null, 2) );

    const ajax = (method, url, callback, payload) => {  // payload는 옵션이기때문에 맨 뒤쪽 인자로 써준다.
      const xhr = new XMLHttpRequest();
      xhr.open(method, url);
      xhr.setRequestHeader('Content-Type', 'application/json');  // get은 이작업을 안해줘도 상관없음.
      xhr.send(JSON.stringify(payload));  // 보내는 것은 위 4줄이 끝! 비동기 처리부분이 아님.

      // respose가 필요한 경우 여기부터 시작
      xhr.onreadystatechange = () => { // 이벤트 프로퍼티 방식은 이벤트 앞에 on을 붙여준다! 예를들면 click앞에 onclick / 이 함수만 비동기처리부분임 이 안에서 에러나면 잡기 힘듬.
        // console.log(xhr.readyState);          // 함수 내부에서는 할일을 적어주면 된다.   readyState는 현재 상태
        if (xhr.readyState !== XMLHttpRequest.DONE) return; // 4번(DONE은 상수)이 아니면 아래쪽에 최종적으로 할일을 적어준다.

        if (xhr.status >= 200 && xhr.status < 400) {  // status는 http 상태 코드, 200은 OK | 201은 POST가 OK | 404 리소스를 요청했는데 자료가 없는경우
          // request가 제대로 되서 제대로 response를 받은 경우 = success
          callback(JSON.parse(xhr.response)); 
        } else {
          // fail
          // 실무에서는 파일에다가 시간정보, 담당자번호 등 다양한 정보를 데이터베이스에 저장
          // console.error('eroor...');
        }
      };  
    };

    try{
      setTimeout(() => {throw Error('error'); }, 1000);
    } catch(e) {
      console.error('error');
      console.log(e);
    }

    
    // try{
    //   ajax('GET', 'http://localhost:3000/todos/3', render);
    // } catch(e){
    //   console.error('error');
    //   console.error(e);
    // }

    // ajax('GET','http://localhost:3000/todos');

    // ajax('POST', 'http://localhost:3000/todos', render, {
    //   id: 4, content: "Angular", completed: true
    // });

    // ajax('DELETE', 'http://localhost:3000/todos/4', render); 

    // ajax('PUT', 'http://localhost:3000/todos/3', render, {
    //   id: 3, content: "React", completed: false
    // });  
    // ajax('PATCH', 'http://localhost:3000/todos/3', render, {completed: true}); 
  </script>
</body>
</html>

 

Promise를 사용한 실습예제

<!DOCTYPE html>
<html lang="en">
</head>

<body>
  <pre class="result"></pre>
  <script>
    const $result = document.querySelector('.result');

    const render = content => ($result.innerHTML = JSON.stringify(content, null, 2));

    const promiseAjax = (method, url, payload) => {  // payload는 옵션이기때문에 맨 뒤쪽 인자로 써준다.
      
      return new Promise((resolve, reject) =>{  // callback을 promise로 호출 , resolve는 성공시 호출 , 실패는 reject
        // 실패하면 실패한 이유를 reject로 호출
        // Promise는 4가지 상태를 가지고 있다. 그중에 성공이냐 실패냐만 알면된다.
        // 성공했으면, then을 쓴다. 실패했으면, catch를 부른다.
        const xhr = new XMLHttpRequest();
        xhr.open(method, url);
        xhr.setRequestHeader('Content-Type', 'application/json');  // get은 이작업을 안해줘도 상관없음.
        xhr.send(JSON.stringify(payload));  // 보내는 것은 위 4줄이 끝! 비동기 처리부분이 아님.

        // respose가 필요한 경우 여기부터 시작
        xhr.onreadystatechange = () => { // 이벤트 프로퍼티 방식은 이벤트 앞에 on을 붙여준다! 예를들면 click앞에 onclick / 이 함수만 비동기처리부분임 이 안에서 에러나면 잡기 힘듬.
          // console.log(xhr.readyState);          // 함수 내부에서는 할일을 적어주면 된다.   readyState는 현재 상태
          if (xhr.readyState !== XMLHttpRequest.DONE) return; // 4번(DONE은 상수)이 아니면 아래쪽에 최종적으로 할일을 적어준다.

          if (xhr.status >= 200 && xhr.status < 400) {  // status는 http 상태 코드, 200은 OK | 201은 POST가 OK | 404 리소스를 요청했는데 자료가 없는경우
            // request가 제대로 되서 제대로 response를 받은 경우 = success
            resolve(JSON.parse(xhr.response));
          } else {
            reject(xhr.status);
          }
        };
      });
    };

    (async function () {
      const res = await promiseAjax('GET', 'http://localhost:3000/todos/');
      console.log(res);
    }());

    // promiseAjax('GET','http://localhost:3000/todos/')
    //   .then(render)  // 콜백을 2개 받는다. 첫번째는 성공 콜백 / 두번째는 실패 콜백 대부분 성공 콜백만 준다 (통상적으로)
    //                  // .then을 계속 써줘서 하는 것 promise 체인이라고 한다. 순서대로 코드를 작성 가능하다.
    //   .catch(console.error());
  </script>
</body>

</html>

현업에서는 비동기 처리를 위하여 Promise를 쓰던가 , async await를 쓰던가. 둘중에 하나로 쓴다.

 

 

Promise는 총 4가지 상태를 갖지만, 아래 2가지가 중요.

fulfilled 비동기 처리가 수행된 상태 (성공) resolve 함수가 호출된 상태
rejected 비동기 처리가 수행된 상태 (실패) reject 함수가 호출된 상태

 

then은 promise를 반환한다.

 

const url = 'http://jsonplaceholder.typicode.com/posts';

    // 포스트 id가 1인 포스트를 검색하고 프로미스를 반환한다.
    promiseAjax('GET', `${url}/1`)
      // 포스트 id가 1인 포스트를 작성한 사용자의 아이디로 작성된 모든 포스트를 검색하고 프로미스를 반환한다.
      .then(res => promiseAjax('GET', `${url}?userId=${JSON.parse(res).userId}`))
      .then(JSON.parse)
      .then(render)
      .catch(console.error);

then then then이 이어짐 = 프로미스 체이닝

이 동작이 가능한 이유는 then이 프로미스를 리턴해주기 때문에 가능하다.

에러는 catch로 잡는다.

 

 

promise는 new를 사용하기 때문에 생성자 함수이다.

대부분의 생성자 함수는 정적 메소드를 가지고 있다. ( ex ) Array.isarray 처럼 )

 

정적 메소드 들

Promise.resolve

Promise.reject

 

Promise.all : 일반적으로 인수로 배열을 준다. 배열안에는 promise객체를 담는다. 그래서 all은 죄다 실행하고 결과값을 배열에다가 담아준다.

Promise.all([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]).then(console.log) // [ 1, 2, 3 ]
  .catch(console.log);

3초 걸린다. all안에 쓴 배열 순서대로 결과가 나온다. 

Promise.all([
  1, // => Promise.resolve(1)
  2, // => Promise.resolve(2)
  3  // => Promise.resolve(3)
]).then(console.log) // [1, 2, 3]
  .catch(console.log);

프로미스 객체가 아니면, 기본적으로 프로미스 객체로 바꿔준다.

const githubIds = ['jeresig', 'ahejlsberg', 'ungmo2'];

Promise.all(githubIds.map(id => fetch(`https://api.github.com/users/${id}`)))
  // [Response, Response, Response] => Promise
  .then(responses => Promise.all(responses.map(res => res.json())))
  // [user, user, user] => Promise
  .then(users => users.map(user => user.name))
  // [ 'John Resig', 'Anders Hejlsberg', 'Ungmo Lee' ]
  .then(console.log)
  .catch(console.log);

all안에 기입한 순서대로 동작한다. 

 

Promise.race

Promise.race([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]).then(console.log) // 3
  .catch(console.log);

레이스는 경쟁시킨다. 먼저 처리된게 먼저 나오고 끝! (1등만 나옴)

첫번째 발생한 에러만 잡고 끝.

 

 

** 깨알상식 :  존레식(jeresig) - jquery 만든사람  / ahejlsberg(아일스 버그) : c#, typescript 만든사람

 

반응형