기록

*65일차 (비동기처리) 본문

학원/강의

*65일차 (비동기처리)

pringspring 2022. 4. 28. 17:35

@비동기처리

자바스크립트는 싱글스레드로 처리된다.

비동기처리함수(Timer API, DOM처리, Event처리, Ajax(XMLHttpRequest))를 만날때만 백그라운드(Web APIs)로 처리를 위임.

콜스택의 동기적작업이 완료되면 콜백함수를 실행하는 구조.

 

  • heap
  • call stack
  • Web APIs
  • Callback Queue : EventLoop에 의해 call stack이 비워질때 순차적(FIFO)을 실행

 

*동기적처리

  • foo실행결과를 기다렸다가 다음코드를 진행. 
  • 순서대로 처리
<button id="btn1">Async - Timer</button>
  <button id="btn2">Async - DOM</button>
  <script>
  btn1.addEventListener('click', () => {
    // 동기적처리 
    // const result = foo();
    // console.log('result :', result)
    
    // 비동기적처리
    let result;
    setTimeout(() => {
      // WebAPIs --> Callback Queue ---> callstack이 비워지면 EventLoop에 의해서 callstack추가/실행
      result = 100;
      console.log('result@timer :', result);
    }, 0);

    console.log('result :', result);
  });

  const foo = () => {
    console.log('foo');
    return 100;
  }

 

*DOM

  • 외부스크립트를 동적으로 로딩해서 실행하기

 

*callback함수

  • 비동기적 처리가 완료되면 실행하는 함수

→ bar호출이 완료되면 car@2.js호출

  btn2.addEventListener('click', () => {  
    // loadScript('js/1.js');
    // bar(); // Uncaught ReferenceError: bar is not defined

    let src;
    // callback함수이용
    loadScript('js/1.js', (script) => { 
      console.log(`${script.src} loading 완료!`);
      bar();
    });


    loadScript('js/1.js', (script) => { 
      console.log(`${script.src} loading 완료!`);
      src = bar();
      loadScript(src, (script) => { 
        console.log(`${script.src} loading 완료!`);
        src = car();
        loadScript(src, (script) => { 
          console.log(`${script.src} loading 완료!`);
          dar();
        });
      });
    });
  });

  /**
   * <script src='js/1.js'>&lt;/script>
   */
  const loadScript = (src, callback) => {
    // console.log(typeof callback, callback);
    const script = document.createElement('script');
    script.src = src;
    script.onload = () => {
      // script태그 loadng완료시 호출한 핸들러로 바인딩
      callback(script); 
    }
    // DOM에 추가 (비동기처리)
    document.head.append(script);

 

*Promise

  • producer code : 비동기
  • consumer code : 콜백
  • Promise는 produce와 consumer코드를 연결시키는 객체
  • callback hell을 제거 , 아래로 코드를 연이어 작성할 수 있다

 

**속성

  • status : pending → 정상처리 fulfilled(이행) / →오류 rejected(거부)
  • result : undefined → 정상처리 value / →오류 예외객체

 

  btn3.addEventListener('click', () => {
    // resolve : 성공시 콜백함수
    // reject : 실패시 콜백함수 
    const promise = new Promise((resolve, reject) => {
      try {
        // 비동기 작업 Producer Code
        console.log('Producing........');
        // throw new Error("비동기 작업중 - 으악!!!!");
        resolve(12345); // callback에 전달할 value값
      } catch (e) {
        reject(e);
      }
    });
    // console.log(promise);

    // then(resolve콜백함수, reject콜백함수)
    promise
      .then((value) => {
        console.log('Consuming.....');
        console.log('성공 : ', value);
      })
      .catch((err) => {
        console.error('실패 : ', err);
      })

  });

 

ex)setTimeout을 promise를 통해 사용하기

 btn4.addEventListener('click', () => {
    timeoutPromise('안녕',  3000)
      .then((value) => {
        console.log(value);
      });
  });
  
    const timeoutPromise = (msg, millis) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(msg), millis);
    });
  };

 

ex)then promise를 리턴하므로, 이후 실행코드는 다시 then절 작성가능

  btn5.addEventListener('click', () => {
    console.log(
      orderPromise()
        .then((value) => {
          console.log(value);
        })
        .then(() => {
          console.log('finished.......');
        })
    );
  });

  const orderPromise = () => new Promise((resolve, reject) => {
    console.log('promise producing....');
    resolve('abc');
  });

 

ex)1.js를 동적으로 로드후 bar호출

btn6.addEventListener('click', () => {
    // loadScript('js/1.js', () => {
    //   bar();
    // });

    loadScriptPromise('js/1.js')
      .then((value) => {
        console.log(`${value} 로딩 완료!`);
        const src = bar();
        return loadScriptPromise(src); // 명시적으로 promise 리턴하기
      })
      .then((value) => {
        console.log(`${value} 로딩 완료!`);
        const src = car();
        return loadScriptPromise(src);
      })
      .then((value) => {
        console.log(`${value} 로딩 완료!`);
        dar();
      });
      
  });
  
  
    const loadScriptPromise = (src) => new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.src = src;
    script.onload = () => resolve(src);
    document.head.append(script);
  });

 

*Promise chain

  • Promise#then는 암묵적으로 promise객체를 리턴한다.
  • Promise#then안에서 명시적으로 Promise객체를 리턴할 수 있다.
  • Promise#then에서 값을 리턴하면 암묵적 Promise객체의 result값이 된다.
 btn7.addEventListener('click', () => {
    new Promise((resolve, reject) => {
      // console.log(resolve); // ƒ () { [native code] }
      // console.log(reject); // ƒ () { [native code] }
      setTimeout(() => resolve(100), 1000);
    })
    .then((value) => {
      console.log(value);
      return value * 2;
    })
    .then((value) => {
      console.log(value);
      return value * 2;
    })
    .then(value => console.log(value));
  });

 

 

*네트워크 통신 : 비동기처리 (XMLHttpRequest 객체)

  • fetch : promise객체로 반환
  btn8.addEventListener('click', () => {
    fetch(USER_URL)
      .then((response) => {
        // 첫 응답메세지가 도착했을때 resolve실행.
        console.log(response);
        return response.json(); // json데이터를 js object 변환
      })
      .then((data) => {
        console.log('data : ', typeof data, data);
        const container = document.querySelector("#fetch-result");
        container.innerHTML = `<table>
  <tr>
    <th>id</th>
    <td>${data.id}</td>
  </tr>          
  <tr>
    <th>company</th>
    <td>${data.company}</td>
  </tr>          
  <tr>
    <th>classroom</th>
    <td>${data.classroom}</td>
  </tr>          
</table>`;

      });
  });

 

 

*json

  • Javascript Object Notation
  • 이종간의 통신에서 data를 주고받기 위한 포맷언어
btn9.addEventListener('click', () => {
    // javascriopt object/array -> json
    const obj = {
      name: '홍길동',
      age: 33,
      sns: ['instagram', 'twitter'],
      family: {
        father: "홍아빠",
        mother: "홍엄마"
      },
      married : false
    };
    // console.log(obj);
    const jsonObj = JSON.stringify(obj);
    // console.log(typeof jsonObj, jsonObj);
    // string {"name":"홍길동","age":33,"sns":["instagram","twitter"],"family":{"father":"홍아빠","mother":"홍엄마"},"married":false}

    // json -> js object
    const other = JSON.parse(jsonObj);
    console.log(typeof other, other);
    
  });

'학원 > 강의' 카테고리의 다른 글

*71일차 (git)  (0) 2022.05.09
*67일차 (jQuery)  (0) 2022.05.02
*64일차 (정규표현식2)  (0) 2022.04.27
*63일차 (Event / 정규표현식)  (0) 2022.04.26
*62일차  (0) 2022.04.25