Asynchronous JavaScript

프최's log·2020년 9월 21일
0

Javascript

목록 보기
25/26
post-custom-banner

동기(synchronous)와 비동기(Asynchronous)

  • 동기 호출
    클라이언트(서버로 접속하는 컴퓨터)가 서버(서비스, 리소스 등을 제공하는 컴퓨터)로 무언가를 요청했을 때, 응답(response)가 올 때까지 어떠한 작업도 하지 않고 대기하다가 응답이 오는 순간부터 작업을 진행한다.

  • 비동기 호출
    클라이언트에서 서버에 A라는 작업을 요청을 하면, 동기 호출과 다르게 클라이언트는 "대기"하지 않는다. 다른 일을 하고 있거나 또다른 요청을 받아서 서버에 넘기고, 서버에서 A 작업이 완료되었을 경우, 이 A 작업을 받아서 해당 작업을 진행한다.

  • 비동기 주요사례

    • DOM Element와 이벤트핸들러
      • 마우스, 키보드 입력
      • 페이지 로딩
    • 타이머
      • 타이머 API(setTimeout, setInetrval 등)
      • 애니메이션 API(requestAnimationFrame API)
    • 서버에 자원요청 및 응답
      • fetch API
      • AJAX(XHR)



브라우저의 비동기 함수 작동원리

Event Loop

  • Javascript의 런타임

    • 'Call Stack' : 코드가 실행될 때 쌓이는 곳
    • 'Heap' : 메모리
    • 'Callback Queue' : 비동기적으로 실행된 콜백함수 보관 영역
  • Web APIs

  • Event Loop의 역할

    • Call Stack과 Callback Queue의 상태를 체크
    • Call Stack이 비었으면, Callback Queue의 첫번째 콜백을 Call Stack으로 넣는데, 이를 반복적으로 실행한다. 이 반복적인 실행 행위를 틱(Tick)이라고 한다.

참조사이트
MDN - Concurrency model and the event loop
Event Loop
JavaScript Event Loop and Asnyc api


Callback

// A,B,C 랜덤출력(순차출력x)
function pStr(str){
  setTimeout(()=>{
    console.log(str);
  }, Math.floor(Math.random() * 100) + 1);
}let printAll = () => {
  pStr("A")
  pStr("B")
  pStr("C")
}
  • 위의 함수를 실행하면 랜덤으로 A,B,C가 출력된다. 위처럼 비동기로 여러 작업을 진행했을 때, 작업별로 소요시간이 달라서 어떤 값이 출력되는지 예상할 수 없게 된다. 우리가 원하는 것은 순차적으로 작업을 진행하는 것 이기 때문에 이를 해결하기 위해 사용하는 것을 callback 이라고 한다.
//  A,B,C 순차적 출력
function pStr(str, callback){
  setTimeout(()=>{
    console.log(str) 
    callback()
  }, Math.floor(Math.random() * 100) + 1);
}

let printAll = () => {
  pStr("A", ()=>{  
    pStr("B", ()=>{
      pStr("C", ()=>{})
    })
   })
}

 callback 함수 구현 시, 앞 전달인자는 'Error', 뒤 전달인자는 '실 데이터값'의 형식으로 많이 보게 될 것이다.(하단 코드 참조)

const someFunc(callback){
   someHappens()
  
  if (err){
    callback(err, null)
  }
  else{
    callback(null, something)
  }
}

callback hell

  • 중첩된 callback 상태 → 가독성이 좋지 않고, 유지보수가 어렵다.

Promise = 콜백 지옥을 해결하는 법

new Promise((resolve, reject) => { ... })

  • resolve : 인자로 받아온 것을 실행하는 역할
  • reject : 인자로 받아 온 것에 대한 '오류','실패'를 반호나하는 역할
  • .then(()=>{}) : resolve가 실행함과 동시에 실제 data를 반환해주는 역할
  • .then.catch((err)=>do something) : reject 경우가 있을 시 활용 → 에러 핸들링이 쉽다
const myFirstPromise = new Promise((resolve, reject) => {
  // do something asynchronous which eventually calls either:
  //
  //   resolve(someValue)        // fulfilled
  // or
  //   reject("failure reason")  // rejected
});

참조사이트
자바스크립트 프라미스: 소개
then과 catch


Promise의 3가지 상태

  • Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태
  • Fulfilled(이행) : 비동기 처리가 완료되어 프로미스가 값을 반환한 상태 = 작업완료
  • Rejected(실패) : 비동기 처리가 실패 또는 오류가 발생한 상태

function pStr(str){
  return new Promise((resolve, reject) =>{
    setTimeout(()=>{
      console.log(str) 
      resolve()
    }, 
      Math.floor(Math.random() * 100) + 1
    )
  })
}
let printAll = () => {
  pStr("A")
  .then(() => {
   return pStr("B")
  })
  .then(() => {
   return pStr("C")
  })
}

Promise Hell

  • Promise Hell을 해결하기 위한 Promise Chaining
    • 콜백 핸들링
    • 예외가 발생했을 시 멈추고 chain 아래 catch(에러 출력)를 찾는다.

Promise.all

  • 여러 개의 프라미스를 동시에 실행시키는 메서드
  • 요소 전체가 '프라미스인 배열'을 인자로 받아서 결과를 담은 배열을 출력한다.(결과를 담은 배열 또한 '프라미스')

let promise = Promise.all([...promises...]);

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(values => console.log(values));
// [1, 2, 3]

Promise.all를 이용한 fetch 활용

프라미스API


Async await

  • async 함수 안에 await 사용가능
    • await는 항상 async 와 함께 써줘야 작동한다.
  • 표현을 동기적으로 활용할 수 있어서 '가독성'이 높아진다.
function pStr(str){
  return new Promise((resolve, reject) =>{
    setTimeout(()=>{
      console.log(str) 
      resolve()
    }, 
      Math.floor(Math.random() * 100) + 1
    )
  })
}
let printAll = async () => {
  const one = await pStr('A');
  const two = await pStr('B');
  const three = await pStr('C');
}
printAll(); //실행시, A,B,C가 순차적으로 실행된다.

// error와 함께 사용할 경우, 하단과 같이 구현한다.
async function someFunc(){
try{ 
  let 변수1 = await 함수1()
  .
  .
  dosomething
  .
  .
}catch{ 
  . 
  error
  .
}
}

참조사이트
자바스크립트 비동기 처리와 콜백 함수
[javascript] async, await를 사용하여 비동기 javascript를 동기식으로 만들자

profile
차곡차곡 쌓아가는 나의 개발 기록
post-custom-banner

0개의 댓글