클라이언트와 서버가 비동기적으로 여러가지 일을 수행하게 하기 위해서(예를 들면 유튜브 영상의 로딩을 기다리면서 댓글을 보거나 좋아요를 누르거나 추천 영상을 보거나 ... 이렇게 여러가지 일은 하는 것!), 콜백을 계속 부르게 되면 중첩이 된다.
콜백... 콜백... 콜백... 함수 안에서 계속 콜백을 외치게 되면 함수도 알아보기 어렵게 복잡해지고 수정보완도 어려워지는데, 이를callback Hell
이라고 한다.
따라서 위의 예시를 피하기 위해 Promise를 사용한다. Promise를 사용하면 함수의 사용이 플랫해지면서 단순하고 알아보기가 쉬워진다. 아래 예시를 보면 알 수 있다.
const printString = (string, callback) => { setTimeout(() => { console.log(string) // string 프린트 callback() // 함수 실행 }, Math.floor(Math.random() * 100) + 1) // 랜덤 시간 주어짐 } const printAll = () => { printString("A", () => { printString("B", () => { printString("C", () => { }) }) })
이렇게 중첩 callback을 써야 차례로 A B C 를 프린트할 수 있다. 반면 Promise는
const printString = (string => { return new Promise ((resolve) => { setTimeout(() => { console.log(string) // string 콘솔에 출력 resolve() // .then 실행 }, Math.floor(Math.random() * 100) + 1) // 랜덤 시간 주어짐 }) } const printAll = () => { printString("A") .then(()=> { return printString("B") // A를 출력한 다음 실행한다. }) .then(()=> { return printString("C") // B를 출력한 다음 실행한다. })
이렇게 플랫하게 순서를 알기도 쉽게 사용할 수 있다.
yes! 🙌
resolve
: promise의 매개변수 중 하나로resolve
를 호출하면.then()
이 실행된다.
reject
: promise의 매개변수 중 하나로reject
를 호출하면.catch()
가 실행된다.
.then()
:resolve
에서 인자를 받아 실행된다.
.catch()
:reject
에서 인자를 받아 실행된다.
쉽게 말해서 성공시resolve
->.then()
실패, 에러시reject
->.catch()
순서이다.let state = true; // true -> resolve const promiseTest = new Promise( (resolve, reject) => { if(state){ resolve('success'); }else{ reject('Error'); } }); promiseTest .then( (result) => { console.log(result); // resolve()에서 받아 실행 }) .catch( (error) => { console.error(error); // reject()에서 받아 실행 }); // 결과로 success 가 콘솔에 뜨게 된다.
yes! 👍
Pending : 요청된 동작이 완료되지 않은 상태
Fulfilled : 요청된 동작이 완료되어 Promise가 결과 값을 반환resolve
->.then()
Rejected : 요청된 동작이 실패하거나 오류가 발생한 상태reject
->.catch()
매개변수를 배열로 받아 주어진 Promise를 모두 이행한다. 위의 예시를 활용해보자.
const promiseTest = (state) => { return new Promise( (resolve, reject) => { if(state){ console.log(state) // 차례로 one two three 가 콘솔에 출력된다. resolve(state); }else{ reject('Error'); } }); } let state1 = promiseTest('one'); let state2 = promiseTest('two'); let state3 = promiseTest('three'); Promise.all([state1, state2, state3]) .then( (values) => { console.log(values); // 배열 ['one', 'two', 'three']가 출력된다. }) .catch( (error) => { console.log(error); });
위의 예시를 실행하면
one two three
['one', 'two', 'three']
Promise {: undefined} 가 출력된다. Promise.all을 통해 배열로 넣어준 인자를 다 돈다.
async/await
의 사용은 이해한다면 더 쉽다. 콜백함수와 프로미스의 단점을 보완했다.const promiseTest = (state) => { return new Promise( (resolve, reject) => { if(state){ console.log(state) resolve(state); }else{ reject('Error'); } }); } const testTest = async() => { const state1 = await promiseTest('one'); const state2 = await promiseTest('two'); const state3 = await promiseTest('three'); } testTest();
마치 동기함수처럼 훨씬 깔끔하고 가독성있다. 함수에 쓸 때
async function 함수이름() {...}
이렇게 쓰면 된다.
require
를 이용해 최상단에 모듈을 불러와야 한다. 이후 사용하면 된다.const fs = require('fs') // 최상단에 모듈을 불러오기 fs.readFile('something.txt', 'utf8', (err, data) => { //사용! if (err) { throw err; } console.log(data);) });
참고로
fs.readFile
는fs.readFile(읽을파일, 옵션, 콜백함수)
로 쓰인다. 옵션은 인코딩방식을 넘기고 안 쓸 수도 있다.
npm install 사용할모듈
으로 사용전 터미널에서 깔아주면 된다. 이후 Node.js의 내장 모듈처럼 js파일 안 최상단에require
으로 불러와 사용하면 된다.