Frontend/프로그래머스 FE 데브코스

[DAY 12] VanillaJS를 통한 자바스크립트 기본 역량 강화 I (4)

BeNI 2022. 11. 1. 22:35
728x90
Module 

1. import

- export 키워드로 내보내진 변수, 함수 등등을 불러올 수 있는 키워드

import name from "module-name"; // module-name 내 export default로 내보내진 것을 가져옴
import * as allname form "module-name"; // allname 이름으로 지정하여 export 된 것을 가져옴
export const NAME = 'EUNA'
export const AGE = '24'

// 함수 export
export default function 함수이름 () { }
import { loadItem } from "module-name" // 모듈내 export된 것 중 특정 값만 가져옴
import loadItem as item from "module-name" // 다른 이름으로 사용하기

* export default vs export

export default : 해당 모듈의 전체 개체를 export 한다는 의미 (하나의 페이지를 그릴때)

export : 복수의 개체가 있는 라이브러리 형태의 모듈에서 가져오기 할 때 사용(함수를 묶어놓은 것들)

 

✅ 장점

- 각 Js별로 사용되는 모듈을 명시적으로 import 해오기 때문에 사용, 사용안되는 스크립트 추적 가능

- script는 불러오는 순서가 중요하지만, import는 순서가 무관하다.

- script src로 불러오는것과 다르게 전역 오염이 일어나지 않음

* import 사용하려면 웹 서버가 필요(+파일이름은 js를 붙여야한다)

 

비동기 다루기 callback

1. 비동기 처리

- 특정 코드의 연산이 끝날 때까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 특성

 

ex) addEventListener() 함수

- 두번째 인자로 넘겨진 함수는 바로 실행되지 않고 이벤트 리스너가 정의한 이벤트 발생시 실행

요소.addEventListener('click', func)

 

ex) setTimeout과 setInterval

- 첫번째 인자로 넘겨진 함수는 바로 실행되지 않고 지정시간만큼 지난 후에 실행

setTimeout(func1, 1000);  // 1초 후 실행
setInterval(func2, 5000); // 5초마다 실행
console.log("hi");

// 콘솔 -> func1 -> func2

⭐ 시간을 0으로 해도 바로 실행되지 않는다. 

 

ex) XMLHttpRequest()

- 데이터를 비동기로 요청하고, 요청 후의 동작을 비동기로 처리

function request (url, suc, fail) {
  const xhr = new XMLHttpRequest();
  xhr.addEventListener("load", (e) => {
    if(xhr.readyState === 4) {
      if(xhr.status === 200) {
        successCallback(JSON.parse(xhr.responseText))
      } else {
        fail(xhr.statusText)
      }
    }
  })
  xhr.addEventListenr('error', (e) => fail(xhr.statusText))
  xhr.open('GET', url);
  xhr.send()
}

 

- 비동기 포기하고 동기 방식으로 코드 작성 가능(사용 x)

function syncRequest (url) {
  const xhr = new XHLHttpRequest()
  
  xhr.open('GET', url, false)
  xhr.send()
  
  if(xhr.status === 200){
    return JSON.parse(xhr.responseText)
  else {
    throw new Error(xhr.statusText)
  }
}

👉 하지만 이러한 방식은 요청 후 응답이 오기 전까지 브라우저가 동작하지 않는다 

 

 

 

Promise

1. Promise

- Promise는 비동기 작업을 제어하기 위해 나온 개념으로 콜백지옥에서 어느정도 벗어날 수 있게 함

- Promise로 정의된 작업끼리는 연결할 수 있고, 코드의 depth가 크게 증가하지 않게해준다

 

1) Promise 만들기

const promise = new Promise((resolve, reject) => {
  // promise 내부에서 비동기 상황 종료시 resolve
  // promise 내부에서 오류 상황일 때, reject
})

- Promise에서는 then을 이용해 비동기 작업 이후 실행할 작업을 지정함

function asyncPromiseWork() {
  return new Promise((resolve, reject) => {
    return resolve('complete')
  })
}

asyncPromiseWork()
	.then(result => asyncPromiseWork(result)
    }).then(result => asyncPromiseWork(result)
    }).then(result => asyncPromiseWork(result)
    })

- reject가 발생했을 경우 catch문으로 잡을 수 있다. (catch문을 안넣으면 chain이 멈춘다)

- finally에서는 성공/실패 여부 상관없이 무조건 실행

- 기존의 콜백함수를 promise 형태로 만들 수 있음

 

ex) 기존 request 함수 promise 형태로 바꾸기

export function request (url) {
 return new Promise((resolve, reject) => {
  const xhr = new XMLHttpRequest();
  xhr.addEventListener("load", (e) => {
    if(xhr.readyState === 4) {
      if(xhr.status === 200) {
        resolve(JSON.parse(xhr.responseText))
      } else {
        reject(xhr.statusText)
      }
    }
  })
  xhr.addEventListenr('error', (e) => reject(xhr.statusText))
  xhr.open('GET', url);
  xhr.send()
 })
}

 

2) 내장 함수

① Promise.all() : 배열 안 모든 promise를 처리 후 then

Promise.all([promise1, promise2, ...]).then(() => {});

 

② Promise.race() : 여러 promise중 하나라도 resolve/reject 되면 종료

Promise.race(iterable)

 

 

③ Promise.any(iterable) : 여러 Promise 중 하나라도 resolve 되면 종료

- reject는 무시하고, resolve 되는 것만 처리

Promise.any(iterable)

⑤ Promise.allSettled(iterable) : 여러 Promise들이 성공했거나, 실패했거나 상관없이 모두 이행된 경우 처리

⑥ Promise.resolve : 주어진 값으로 이행하는 Promise.then 객체를 만듬, 주어진 값이 Promise인 경우 Promise가 반환

* 항상 Promise를 반환해야할 때 유용하다.

 

 

 

async, await

1. async, await

- Promise를 이용해도 코드 작성에 불편함이 있어 해결하기 위해 등장

- 동기식 코드처럼 보이는 장점이 있다.

 

ex) then 중첩 문을 async, await 문으로 작성하기

const delay = (delayTime) => {
  return new Promise(resolve => setTimeout(resolve, delayTime));
}

const work = () => {
  console.log('work run')
  delay(1000)
    .then(() => {
      console.log('work 1 done');
      return delay(1000)
    })
    .then(() => {
      console.log('work 2 done');
      return delay(1000)
    })
    .then(() => {
      console.log('work 3 done');
      return delay(1000)
    })
    .then(() => {
      console.log('work 4 done');
      return delay(1000)
    })
}

work();
const work = async () => {
  console.log('work run') 
  await delay(1000)
  console.log('work 1 done');

  await delay(1000)
  console.log('work 2 done');

  await delay(1000)
  console.log('work 3 done');

  await delay(1000)
  console.log('work 4 done');
}

- 굉장히 코드가 깔끔해지는 것을 볼 수 있다.

 

1) 선언 방식 2가지

async function asyncFunction () {
  const res = await request(...)
}
const asyncFunction = async () {
  const res = await request(...)
}

- async 키워드 함수가 붙은 함수는 실행결과를 Promise로 감싼다

- 기본적으로 await는 async로 감싸진 함수 scope에서만 사용 가능했지만, top level await가 등장하여

  top level에서도 사용 가능하다.

 

 

 

 

728x90