js 비동기 처리 (callback, promise, async/await)
https://joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation/ 에서 참조하여 작성했습니다.
비동기 처리 -> JS의 특징으로 instruction이 끝날 때까지 process를 멈추지 않고 다음 instruction을 실행하는 특성
이런 비동기처리 방식의 특징을 갖는 js에서 동기처리를 해야할 때가 있다면?
예시)
위와 같은 코드에서 동기식 처리에서는 hello가 나오고 3초후 Bye 그리고 Hello Again이 나와야한다.
하지만 비동기식 처리에서는 hello가 나오고 hello again이 나오고 3초후 Bye가 나온다.
1. 콜백 함수형
예를 들어 위와 같은 코드에서 getData() 함수를 살펴보자.
getData에는 $.get으로 1번째 상품의 정보를 얻어온후 이 값을 콜백함수의 인자인 response로 넘겨 tableData로 주는 것을 확인할 수 있다.
만약 callback 함수로 처리하지 않았을 경우 HTTP GET request로 부터 받은 response가 오기도 전에 tableData를 리턴할 수 있다.
이는 callback 함수에 해당하는 함수를 따로 만들어 다음과 같이 작성할 수 있다.
문제는 다음과 같이 콜백함수를 연속으로 사용할 때이다.
이럴 경우 다음과 같이 수정가능하다.
2. promise 형
비동기처리 방식을 좀 더 간단하게 사용하는 방법이 있다.
바로 Promise이다. Promise를 사용하려면 총 3가지의 상태를 기억하면 된다.
1. pending 상태: 비동기 처리 로직이 아직 완료되지 않은 상태
2. fulfilled 상태: 비동기 처리가 완료하여 결과 값을 반환해준 상태
3. rejected 상태: 실패한 상태.
Promise의 인스턴스가 만들어지면 해당 로직은 pending 상태가 된다.
또한 콜백 함수의 인자로 resolve와 reject를 사용하는데 이는 각각 이행상태와 실패상태를 의미한다.
예시들
에러 캐치는 다음과 같이:
주의점 resolve가 return을 의미하는것은 아니기 때문에 함수의 종결을 의미하는 것은 아니다.
3. async & await
promise 객체를 반환하는 함수를 이용하여 .then과 같이 사용하지 않아도 된다.
예제
다음과 같은 코드에서 두 함수는 promise 객체를 반환하게 된다.
따라서 다음과 같이 사용이 가능하다.
비동기 처리 -> JS의 특징으로 instruction이 끝날 때까지 process를 멈추지 않고 다음 instruction을 실행하는 특성
이런 비동기처리 방식의 특징을 갖는 js에서 동기처리를 해야할 때가 있다면?
예시)
// #1
console.log('Hello');
// #2
setTimeout(function () {
console.log('Bye');
}, 3000);
// #3
console.log('Hello Again');
위와 같은 코드에서 동기식 처리에서는 hello가 나오고 3초후 Bye 그리고 Hello Again이 나와야한다.
하지만 비동기식 처리에서는 hello가 나오고 hello again이 나오고 3초후 Bye가 나온다.
1. 콜백 함수형
function getData() {
var tableData;
$.get('https://domain.com/products/1', function (response) {
tableData = response;
});
return tableData;
}
console.log(getData()); // undefined
예를 들어 위와 같은 코드에서 getData() 함수를 살펴보자.
getData에는 $.get으로 1번째 상품의 정보를 얻어온후 이 값을 콜백함수의 인자인 response로 넘겨 tableData로 주는 것을 확인할 수 있다.
만약 callback 함수로 처리하지 않았을 경우 HTTP GET request로 부터 받은 response가 오기도 전에 tableData를 리턴할 수 있다.
이는 callback 함수에 해당하는 함수를 따로 만들어 다음과 같이 작성할 수 있다.
function getData(callbackFunc) {
$.get('https://domain.com/products/1', function (response) {
callbackFunc(response); // 서버에서 받은 데이터 response를 callbackFunc() 함수에 넘겨줌
});
}
getData(function (tableData) {
console.log(tableData); // $.get()의 response 값이 tableData에 전달됨
});
문제는 다음과 같이 콜백함수를 연속으로 사용할 때이다.
$.get('url', function (response) {
parseValue(response, function (id) {
auth(id, function (result) {
display(result, function (text) {
console.log(text);
});
});
});
});
function parseValueDone(id){
auth(id, authDone);
}
function authDone(result) {
display(result, displayDone);
}
function displayDone(text) {
console.log(text);
}
$.get('url', function (response) {
parseValue(response, parseValueDone);
});
2. promise 형
비동기처리 방식을 좀 더 간단하게 사용하는 방법이 있다.
function getData() {
return new Promise(function (resolve, reject) {
$.get('url 주소/products/1', function (response) {
resolve(response);
});
});
}
getData().then(function (tableData) {
console.log(tableData);
});
바로 Promise이다. Promise를 사용하려면 총 3가지의 상태를 기억하면 된다.
1. pending 상태: 비동기 처리 로직이 아직 완료되지 않은 상태
2. fulfilled 상태: 비동기 처리가 완료하여 결과 값을 반환해준 상태
3. rejected 상태: 실패한 상태.
Promise의 인스턴스가 만들어지면 해당 로직은 pending 상태가 된다.
new Promise();
또한 콜백 함수의 인자로 resolve와 reject를 사용하는데 이는 각각 이행상태와 실패상태를 의미한다.
function getData() {
return new Promise(function (resolve, reject) {
var data = 100;
resolve(data);
});
}
// resolve()의 결과 값 data를 resolvedData로 받음
getData().then(function (resolvedData) {
console.log(resolvedData); // 100
});
function getData() {
return new Promise(function (resolve, reject) {
reject(new Error("Request is failed"));
});
}
// reject()의 결과 값 Error를 err에 받음
getData().then().catch(function (err) {
console.log(err); // Error: Request is failed
});
예시들
new Promise(function(resolve, reject){
setTimeout(function() {
resolve(1);
}, 2000);
})
.then(function(result) {
console.log(result); // 1
return result + 10;
})
.then(function(result) {
console.log(result); // 11
return result + 20;
})
.then(function(result) {
console.log(result); // 31
});
getData(userInfo)
.then(parseValue)
.then(auth)
.then(diaplay);
var userInfo = {
id: 'test@abc.com',
pw: '****'
};
function parseValue() {
return new Promise({
// ...
});
}
function auth() {
return new Promise({
// ...
});
}
function display() {
return new Promise({
// ...
});
}
에러 캐치는 다음과 같이:
// catch()로 오류를 감지하는 코드
function getData() {
return new Promise(function (resolve, reject) {
resolve('hi');
});
}
getData().then(function (result) {
console.log(result); // hi
throw new Error("Error in then()");
}).catch(function (err) {
console.log('then error : ', err); // then error : Error: Error in then()
});
주의점 resolve가 return을 의미하는것은 아니기 때문에 함수의 종결을 의미하는 것은 아니다.
3. async & await
promise 객체를 반환하는 함수를 이용하여 .then과 같이 사용하지 않아도 된다.
function fetchItems() {
return new Promise(function(resolve, reject) {
var items = [1,2,3];
resolve(items)
});
}
async function logItems() {
var resultItems = await fetchItems();
console.log(resultItems); // [1,2,3]
}
예제
function fetchUser() {
var url = 'https://jsonplaceholder.typicode.com/users/1'
return fetch(url).then(function(response) {
return response.json();
});
}
function fetchTodo() {
var url = 'https://jsonplaceholder.typicode.com/todos/1';
return fetch(url).then(function(response) {
return response.json();
});
}
다음과 같은 코드에서 두 함수는 promise 객체를 반환하게 된다.
따라서 다음과 같이 사용이 가능하다.
async function logTodoTitle() {
var user = await fetchUser();
if (user.id === 1) {
var todo = await fetchTodo();
console.log(todo.title); // delectus aut autem
}
}
댓글
댓글 쓰기