9-3 비동기, Promise, async & await
동기 : 동시에 일어나는 것, 요청과 결과가 동시에 일어남. 순서에 따라 작업이 진행되므로, 여러가지 요청을 동시에 처리하지 않음(느린처리).
비동기 : 흐름의 순서와 관계없이(이벤트가 완료될 때까지 기다리지않고) 작업이 처리되어, 요청과 결과가 동시에 일어나지 않음(빠른처리).
저번에 작성한 주문api 코드에서, delivery_id 와 order_id를 받기위해 변수만 선언하면
값이 undefined되어서 null이라고 에러가 발생합니다.
// 주문하기
const order = (req, res) => {
const { items, delivery, totalQuantity, totalPrice, userId, firstBookTitle } = req.body;
let delivery_id;
let order_id;
let sql = "INSERT INTO delivery (address, receiver, contact) VALUES (?, ?, ?)";
let values = [delivery.address, delivery.receiver, delivery.contact];
conn.query(sql, values,
(err, results) => {
if (err) {
console.log(err);
return res.status(StatusCodes.BAD_REQUEST).end();
}
delivery_id = results.insertId;
console.log("result id", results.insertId);
console.log("conn query", delivery_id);
})
console.log("out", delivery_id);
~
~
로그에 값을 출력해보면 "conn query"에서의 delivery_id는 값이 들어가있지만 아래 "out"의 delivery_id는 undefined 입니다.
(order_id 도 마찬가지)
Node의 특징인 non blocking, 비동기 방식으로 동작하기에 값이 들어가기 이전에 호출이 되어서 발생하는 문제입니다.
이전에 실행되는 코드들을 기다린 다음 실행될 수 있도록 해주어야 합니다.
방법
Promise() 객체
Promise 객체는 작업 완료시 resolve or reject 둘 중 하나는 무조건 실행한다고 약속
let pro = new Promise(function(resolve, reject) {
setTimeout(() => resolve("완료"), 2000);
})
pro.then(function(result){console.log(result)}, function(err){});
=> 2초뒤 완료 log출력됨
let pr = new Promise(function(reslove, reject) {
setTimeout(() => reslove("완료"), 2000);
}).then(
function(result) {
console.log(result);
return result + "!";
},
function(error){}
).then(
function(result) {
console.log(result);
return result + " !!";
},
).then(
function(result) {
console.log(result);
return result + " !!!"
}
)
=>
완료 (성공)
완료! (성공)
완료! !! (성공)
완료! !! !!! (성공)
async function f() {
// 1
// promise 객체 한개당 => query 하나
let promise1 = new Promise(function (resolve, reject) {
setTimeout(() => resolve("완료1"), 2000);
});
let result1 = await promise1; // Promise 객체가 일 다 할때까지 기다려줌
console.log(result1);
// 2
let promise2 = new Promise(function (resolve, reject) {
setTimeout(() => resolve("완료2 with " + result1), 2000);
});
let result2 = await promise2
console.log(result2);
// 3
let promise3 = new Promise(function (resolve, reject) {
setTimeout(() => resolve("완료3 with " + result2), 2000);
});
let result3 = await promise3;
console.log(result3);
}
f();
=>
완료1
완료2 with 완료1
완료3 with 완료2 with 완료1
그러면 위와같이 async await이나 promise를 사용하기만 하면 해결이 되나? 9-4
기타 보충:
async await 을 보면 순차적으로 실행할 수 있으니까 무조건 동기적으로 처리되는구나 할 수 있는데 사실 그렇게 보이는 것일 뿐.
비동기적으로 처리되고 있는 중.
저번에 Node특징 정리할 때 알아본 동작방식 중
Nodejs는 싱글 스레드 이지만, 싱글 스레드라고 한 이유는 개발자가 컨트롤 가능한 스레드가 한 개 이기 때문에 싱글스레드로 동작한다고 한 것, 실제로는 여러개의 스레드로 처리가 되는 것.
라고 하였는데, async 하는 스레드만 해당 함수내에서 기다리는 것이고, 메인 스레드에서는 계속해서 다른 작업이 처리됩니다.