TIL 18일차 - [JS/Node] 비동기

tamagoyakii·2021년 11월 9일
0

TIL

목록 보기
18/31
post-thumbnail

✅ synchronous / asynchronous

  • 동기 -> 전화
    하던일을 멈추고 받아야 한다.(blocking)
    요청에 대한 결과가 동시에 일어난다.(synchronous)

  • 비동기 -> 문자
    확인 후 나중에 답장할 수 있다.(non-blocking)
    요정에 대한 결과가 동시에 일어나지 않는다.(asynchronous)

✅ 비동기의 주요 사례

  1. DOM Element의 이벤트 핸들러
    마우스, 키보드 입력
    페이지 로딩

  2. 타이머
    타이머 API
    애니메이션 API

  3. 서버의 자원 요청 및 응답
    fetch API
    AJAX(XHR)

🍦 Achievement Goals 🍦

  • 어떤 경우에 중첩된 callback이 발생하는지 이해할 수 있다.

    callback은 async를 제어하기 위해 사용한다. 아래는 string을 출력해주는 함수이다.

    
    const printString = (string, callback) => {
        setTimeout(() => {
        	console.log(string)
            callback()
            },
            Math.floor(Math.random() * 100) + 1
        )
    }

    위 함수를 사용히여 "A", "B", "C"를 출력할 때, 함수를 그냥 나열하여 사용하면 string은 입력 순서가 아닌 랜덤 순서대로 출력된다. 따라서 "A", "B", "C"를 차례로 나열하고 싶을 때에는 아래와 같이 callback함수를 중첩하여 사용해야 한다.

    
    const printAll = () => {
        printString("A", () => {
        	printString("B", () => {
                printString("C", () => {})
            })
        })
    }
    printAll();
  • 중첩된 callback의 단점, Promise의 장점을 이해할 수 있다.

    위의 경우 callback 함수가 3개밖에 없기 떄문에 함수를 이해하는 데에 큰 어려움이 없지만, 중첩된 callback함수가 너무 많으면 함수의 가독성이 떨어지고 함수를 관리하기가 어려워진다. 이를 "callback HELL"이라고 부른다. 이를 해결하기 위해 Promise를 사용한다. Promise는 코드의 깊이가 평탄해서 callback 패턴에 비해 유지보수에 용이하다. 또 다른 비동기 작업을 쉽게 추가하거나 수정할 수 있다.

  • Promise 사용 패턴을 이해할 수 있다.

    Promise는 함수를 만들 때 callback이 아닌, resolvereject 함수를 인자로 받으며, new Promise를 리턴한다.

    resolvereject
    resolve 와 reject 는 함수로서 호출되면 promise 를 이행하거나 거부한다. 이 둘을 이용하여 비동기 작업이 모두 끝나면 resolve 를 호출해 이행하고, 중간에 오류가 생기면 reject 를 이용해 거부한다.

    thencatch

    
    const promise = new Promise((resolve, reject) => {
        setTimeout(() => {
        	resolve("resolve")
            },
            Math.floor(Math.random() * 100) + 1
        )
    }
    
    promise.then((result) => console.log(result));

    위의 경우 promise가 종료되면 resolve 값을 then으로 받는다. 하지만 reject의 경우는 then으로 받을 수 가 없다. 그럴 때 catch를 사용한다.

    
    const promise = new Promise((resolve, reject) => {
        setTimeout(() => {
        	reject("reject")
            },
            Math.floor(Math.random() * 100) + 1
        )
    })
    
    promise.then((result) => console.log(result)).catch((err) => console.log(err));

    thencatch는 절대 같이 실행될 수 없다. 무조건 resolve시에 then, reject시에 catch가 실행된다.

  • Promise의 세 가지 상태를 이해할 수 있다.

    pedding(대기) : resolve 할지 reject 할 지 결정되지 않은 초기의 상태이다.
    fullfilled(이행) : 연산이 성공한 상태이다.
    rejected(거부) : 연산이 실패한 상태이다.

  • Promise.all 의 사용법을 이해할 수 있다.

    Promise.all은 주어진 모든 Promise 를 실행한 후 진행되는 하나의 Promise를 배열로 반환한다. 사용법은 아래와 같다.

    
    const promise1 = Promise.resolve(3);
    const promise2 = 42;
    const promise3 = new Promise((resolve, reject) => {
      setTimeout(resolve, 100, 'foo');
    });
    
    Promise.all([promise1, promise2, promise3]).then((values) => {
      console.log(values);
    });
  • async/await keyword에 대해 이해하고, 작동 원리를 이해할 수 있다.

    async await을 사용하면 비동기 함수를 동기적인 것 처럼 사용할 수 있다. 이는 코드의 가독성을 높여준다. 아래는 async await의 기본 문법이다

    
    async function 함수명() {
      await 비동기_처리_메서드_명();
    }

    async가 붙은 함수는 반드시 Promise를 반환하고, Promise가 아닌 것은 Promise로 감싸 반환한다. async 함수 안에서 await 키워드를 만나면 Promise가 처리될 때까지 기다리고, 결과는 그 이후에 반환된다. 기다리는 동안엔 엔진이 다른 일을 할 수 있기 때문에, CPU 리소스가 낭비되지 않는다. 아래는 간단한 예제이다.

    
    const gotoSchool = () => {}
    const takeClass = () => {}
    const eatLunch = () => {}
    const goHome = () => {}
    
    const dailyRoutine = async() => {
        const one = await gotoSchool();
        console.log(one);
    
        const two = await takeClass();
        console.log(two);
    
        const three = await eatLunch();
        console.log(three);
    
        const four = await goHome();
        console.log(four);
    
  • Node.js의 fs 모듈의 사용법을 이해할 수 있다.

    Node.js는 비동기 이벤트 기반의 자바스크립트 런타임이다. 따라서 비동기 흐름이 타이머, DOM 이벤트로 한정되어있는 브라우저에서와 다르게 Node.js에는 많은 API가 비동기로 작성되어있다. fs module (= File System module) 이란, 파일 처리와 관련된 전반적인 작업을 하는 모듈을 말한다. 사용하기 위해서는 코드의 최상단에 require 구문을 이용하여 파일을 불러와야 한다.

    const fs = require('fs')

    fs.readFile(path[,options], callback)
    : 인자 세 개를 받아 비동기적으로 파일 내용 전체를 읽는다.

    1. path\<string>|\<Buffer>|\<URL>|\<integer>
      : 파일 이름 => 4가지 타입. 일반적으로 string 타입이다.
    2. options\<Object>|\<string>
      : 선택적 인자 => 객체 또는 문자열(encoding)
    3. callback\<Function>
      : 파일을 일고난 후 비동기적으로 실행되는 함수
      err\<Error> : 에러 발생 안하면 null
      data\<string>|\<Buffer> : 파일의 내용 => 문자열 또는 버퍼(encoding 없을 시)
    
    const getDataFromFile = function (filePath, callback) {
        fs.readFile(filePath, "utf-8", (err, data) => {
        	if(err) {
          	    return callback(err, null);
        	}
            else {
        	    return callback(null, data);
            }
        })
    }

0개의 댓글