promise는 비동기 처리를 위해 있는 객체이다.
여기서 동기처리, 비동기처리란?
예를 들어, 집안일을 한다고 가정해보자.
동기식 : 세탁기를 돌리고, 빨래가 종료되면 그제서야 바닥에 청소기를 돌린다.
비동기식 : 세탁기를 돌려놓고, 빨래가 돌아가는 동안, 바닥 청소하고 설거지하다가 세탁기가 종료되면 세탁물을 꺼낸다.
즉, 비동기는 코드의 효율성을 극대화 할 수 있는 처리방식이다!
아래의 코드를 보자. setTimeout은 대표적인 비동기식 함수이다!!
(일단, 구동은 하는데 백그라운드에 대기만 시켜놓고 작업이 끝나면 실행을 해준다.)
const pr = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('hello promise');
},1000);
});
function test() {
return 'hi';
}
console.log(test()); // hi
console.log(pr); // pending
promise는 단순하게 그냥 비동기식으로 구동하기 위해 사용하는 객체이다.
생성자를 이용해서 pr을 프로미스 객체로 만들어주는 것!!
만약 동기식이라면 hi, hello promise
이렇게 출력이 되겠지만, pr라는 promise 객체는 구동 후 백그라운드에 박혀있다가 1초(1000) 뒤에 실행이 되기때문에
정작 출력은 hi, pending 이런식으로 나온다.
그 이유?
test 함수를 만났으니 일단 hi가 출력되는 건 당연하다.
근데 곧바로 test 함수가 끝나자마자 (아주빠른 시간) 만난 게 console.log(pr)이다.
pr (promise 객체) 은 코드가 구동되고 1초 뒤에 실행이 될 예정인데, 1초가 안 돼서 백그라운드에 쳐박혀있는데,
console.log가 1초 이따 나온다는 애를 자꾸 부르니까 아직 없다고. 실행되지 않았다고 나오는 표시이다. -> <pending>
이해를 돕기 위한 응용 코드를 보자. (async 사용)
필요한 사전 지식
async란? 함수 앞에 붙여서 Promise 객체화 시켜주어, 비동기식으로 구동할 거라고 컴퓨터에게 알려주는 함수
const pr = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('hello promise');
},1000);
});
function test() {
return 'hi';
}
console.log(test()); // hi
async function test2() {
return 'hi';
}
console.log(test2()); // Promise { 'hi' }
console.log(pr); // Promise { <pending> }
pr.then(data=>{
console.log(data); // hello promise
});
일단 출력 결과를 먼저 보자.
test()함수는 마찬가지로 그냥 아무 문제없이 hi로 출력이되었음.
문제는, test2()부터인데, 이 함수 앞에 async를 입력해주었기때문에 promise객체가 되었기 때문에,
객체의 형태로 출력되는 것이다.
여기까진 입력순서대로 출력이 되었고,
console.log(pr)부터 역시 pending이 출력된다. 방금 전 위에 있는 예제의 설명과 동일하게,
코드 구동 시작하고 1초 뒤에 실행할 건데(그래서 백그라운드에서 대기중인데), 자꾸 부르니까. 없다고, 대기중이라고
pending을 출력하는 것이다.
그 다음, 처음보는 부분!
pr.then(data=>{
console.log(data);
then이란?
비동기식 코드가 백그라운드에서 나오면(대기가 끝나면, 즉 종료되면) 그 때 이어서 실행하겠다.
따라서 마지막 코드를 해석해보면
pr이라는 변수의 프로미스객체가 종료되면(구동하고 1초가 지나면)
그 때 return값 을 data라는 변수에 넣어주고 그 값을 출력하겠다. 라는 의미이다.
따라서 맨 위에 적었던 pr의 결과 값인 "hello promise"가 출력되는 것이다.
심화 예제 1 (사실 나한테만 심화임)
윗부분은 (test(), test2()) 동일
const pr = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('hello promise');
},1000);
});
function test() {
return 'hi';
}
console.log(test()); // hi
async function test2() {
return 'hi';
}
console.log(test2()); // Promise { 'hi' }
console.log(pr); // Promise { <pending> }
pr.then(data=>{
console.log(data); // hello promise
});
function test3() {
let i = 0;
pr.then(data=>{
i++;
console.log(data); // hello promise
});
return i;
}
console.log(test3());
출력결과를 미리 보자.
hi, promise hi, promise pending까지는 전 문제와 동일하고(console.log(pr)까지), 그 뒤부터 설명하겠다.
전과 달리,
pr.then(data=>{
console.log(data);
의 출력값이 바로 나오지 않는 이유는 역시 pr이 백그라운드에서 빠져나와(1초동안 갇혀있음) 실행되기 전에 test3()이 먼저 실행되기 때문이다!!
여기서 의문점 ) 아니 그럼 i++ 해줬는데 1이 출력되지 않고, 왜 0이 출력되는가?
function test3() {
let i = 0;
pr.then(data=>{
i++;
console.log(data);
});
return i;
}
------------------------------
let i =0으로 정의된 상태에서,
pr.then~ 구문은 pr이 종료되면 그때서야 실행하기 때문이다. 그래서 i가 0일 때 이미 출력되고 나서, 그제야 i이 뒤늦게 +1 된 것이다.
만약 1을 출력하고 싶다면?
console.log(data)
바로 밑줄에 console.log(i)를 추가해주면 된다. (살짝 야매인게 밑에 return 때문에 0이 먼저 출력 되고 1이 나옴 그래서 다른 방법을 소개하겠다)
심화 예제 2 (사실 나한테만 심화임)
1을 맘편하고 가독성있고 쉽게 출력하는 법
심화 예제 1 코드에서 test3()을 아래코드로 치환해주면 된다.
await 설명아래에
const pr = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('hello promise');
},1000);
});
function test() {
return 'hi';
}
console.log(test()); // hi
async function test2() {
return 'hi';
}
console.log(test2()); // Promise { 'hi' }
console.log(pr); // Promise { <pending> }
pr.then(data=>{
console.log(data); // hello promise
});
async function test3() {
let i = 0;
let podo = await pr;
i++;
console.log(i); // 1
return i;
}
console.log(test3());
await이란?
※ promise 객체에서 await을 만나면, promise 객체가 끝날 때까지 await구문에서 코드가 멈춘다!
출력결과 미리 확인하기
async function test3() {
let i = 0;
let podo = await pr;
i++;
console.log(i); // 1
return i;
}
console.log(test3());
코드 해석 : i를 0으로 정의한다. await pr을 변수 podo에 저장해두고, 위에 있는 pr이라는 promise 객체가 실행되어 종료될 때까지 그 아래코드를 실행하지 않는다.(= pr이 종료되자마자 아래 코드를 실행한다.)
console.log(test3())을 실행했을 때, test3()이라는 프로미스 객체 함수가 await때문에 중도에 멈췄기 때문에
console엔 promise <pending>이 찍힐 수밖에 없다.
그리고 지정했던 1초가 지나고 나서야, pr이 종료되면 await이후 구문인 i++부터 실행된다.
따라서 i+1이 되고 1이 찍히게 된다.
끝
'백엔드 > Node.js' 카테고리의 다른 글
[nodejs]쿠키란?, 로그인 페이지 만들기(cookie parser 사용 안하고) (0) | 2022.02.07 |
---|---|
[nodejs] 게시판 만들기 CRUD(글쓰기, 읽기, 수정하기, 삭제하기) (0) | 2022.02.03 |
[nodejs] 템플릿 엔진 nunjucks 설치, 세팅, 사용하기 (0) | 2022.01.28 |
[nodejs] 구조분해 할당, 객체 리터럴, require, 랜덤함수, promise (1) | 2022.01.27 |
[nodejs] nodejs로 서버로 홈페이지 열기(express 라이브러리 사용) (0) | 2022.01.26 |