동기 작업과 비동기 작업
동기 작업
: 하나의 작업을 실행하고 마친 뒤에 다음 작업을 순차적으로 실행함
비동기 작업
: 메인 흐름은 멈추지 않는 상태에서 특정 작업들을 백그라운드에서 처리하여 동시에 처리하는 것처럼 실행함
비동기 작업을 할 때 가장 많이 사용하는 방식이 콜백 함수를 이용하는 방식이다.
선언적으로 콜백함수를 만들고 간단한 비동기 흐름을 만드는 예제.
<script>
/* 동기 작업과 비동기 작업
동기 작업 : 하나의 작업을 실행하고 마친 뒤에 다음 작업을 순차적으로 실행함
비동기 작업 : 메인 흐름은 멈추지 않는 상태에서 특정 작업들을 백그라운드에서
처리하여 동시에 처리하는 것처럼 실행함
비동기 작업을 할 때 가장 많이 사용하는 방식이 콜백 함수를 이용하는 방식이다.
선언적으로 콜백함수를 만들고 간단한 비동기 흐름을 만들어 본다. */
function sayHello () {
console.log('Hellow world');
}
/* 동기적 실행코드 */
// sayHello();
// console.log('end!');
/* 비동기적 실행 코드*/
setTimeout(sayHello, 3000);
console.log('end!');
</script>
비동기적 실행 코드
setTimeout으로 Hello world 출력을 예약하고 코드는 이어서 실행되기 때문에 end가 먼저 출력되고 3초 뒤 Hello world가 출력된다.
비동기 처리를 하기 위한 가장 흔한 방법은 콜백함수를 이용하는 것이다.
특정 비동기 처리 이후 수행해야 할 내용을 또 정의해야하는 경우에는 콜백 함수의 중첩이 생기고 이러한 것들이 많이 추가되면 콜백 지옥이 생길 수 있다.
function increase(number, callback) {
setTimeout(
() => {
const result = number + 10;
if(callback) {
callback(result);
}
},
1000
);
}
/* 여러번 순차적으로 1초마다 10씩 증가하게 하고싶다면
중첩을 이용해서 호출할 수 있다.*/
console.log('start');
increase(0, result => {
console.log(result);
increase(result, result => {
console.log(result);
increase(result, result => {
console.log(result);
increase(result, result => {
console.log(result);
increase(result, result => {
console.log(result);
console.log('end');
});
});
});
});
});
Promise
: 비동기 처리에 활용되는 객체.
콜백 지옥같은 코드가 형성되지 않게 하는 방안으로 ES6에서 도입되었다.
가독성이 좋아진다.
Promise 함수에 전달되는 두 가지 매개변수
resolve : 성공
reject : 실패
성공 시와 실패 시 호출할 함수를 의미한다.
Promise라는 객체 쪽으로 함수를 하나 전달한다.
그 함수는 내부 적으로 호출할 때 두 개의(resolve, reject) 값을 전달해준다.
그 두개의 값은 둘 다 함수이다.
성공 시에 성공함수, 실패 시에 실패 함수를 전달한다.
function increase(number) {
/* resolve는 성공, reject는 실패를 의미 */
const promise = new Promise((resolve, reject) => {
setTimeout (
() => {
const result = number + 10;
if(result > 50) {
const e = new Error('NumberTooBig');
/* 실패 시 결과 값을 reject로 전달 */
return reject(e);
}
/* 성공 시 결과 값을 resolve의 인자로 전달 */
resolve(result);
},
1000
);
});
return promise;
}
Promise
에서 resolve함수로 전달한 값은 then 메소드(반환된 결과 값을 꺼내는 메소드)를 통해 콜백 함수의 매개변수(여기서는 number)를 이용해서 받아올 수 있다.
비동기 작업을 연달아서 수행한다고 해서 이전 예제처럼 콜백 지옥이 생기는 것이 아니라 promise 객체를 반환받아 then 메소드를 통해 그 다음 작업을 설정하기 때문에 코드 가독성이 개선된다.
increase(0)
.then(number => {
console.log(number);
return increase(number); // 처리 후 다시 promise를 리턴한다.
})
.then(number => {
console.log(number);
return increase(number);
})
.then(number => {
console.log(number);
return increase(number);
})
.then(number => {
console.log(number);
return increase(number);
})
.then(number => {
console.log(number);
return increase(number);
})
.catch(e => { //에러가 발생하는 것을 catch에서 잡는다.
console.log(e);
})
async/await
: Promise를 더 쉽게 사용할 수 있다.
(ES2017(ES8)에서 추가)
함수 선언부 : ascync
키워드를 이용
함수 내부 : promise를 사용할 때 await
키워들 이용
await 키워드가 붙은 promise 호출 구문은 promise 작업이 끝날 때까지 기다리며 실행하게된다.
async function run() {
try{
let result = await increase(0);
console.log(result);
result = await increase(result);
console.log(result);
result = await increase(result);
console.log(result);
result = await increase(result);
console.log(result);
result = await increase(result);
console.log(result);
result = await increase(result);
console.log(result);
} catch(e){
console.log(e);
}
}
run();