오봉이와 함께하는 개발 블로그
JavaScript - 비동기 본문
728x90
비동기
- JavaScript를 사용하는 SPA는 JavaScript에서 제공하는 비동기 함수를 사용한다.
callback
- JavaScript에서 함수는 객체
- 함수의 파라미터로 함수를 전달하여 실행하는 함수를 callback 함수라고 한다.
- 비동기성을 구현해주는 기능 자체를 callback이라 하는 것이 아니라, 비동기성을 구현하기 위해 callback을 사용하는 것
- 비동기성 함수를 호출할 때는 제어권이 넘어가지 않지만, 동기성 함수를 호출할 때는 제어권이 넘어가게 된다.
- 비동기 함수에 callback이 있다면, 해당 callback은 pending되어 있다가 함수가 종료되었을 때 해당 callback을 실행
- 일반 함수에 callback을 사용하는 것은 실행 순서를 보장하는 내부 함수를 사용하는 것
- callback의 핵심은 비동기 함수 안에 callback을 작성하여 비동기 함수가 완료될 때 callback이 정상적으로 작동하도록 하는 것
// callback 예시
function callBack_plus(num1, num2, callback) {
callback(num1 + num2);
}
function result(result) {
console.log("두 수의 합은 " + result + " 입니다.");
}
callBack_plus(3, 3, result);
// 비동기 callback 예시
function requestServer(callback) {
$.get("http://www.dq.com/test.jsp?name=ktko&age=30", function(response) {
callback(response);
});
}
requestServer(function(result) {
console.log(result);
});
// 잘못된 비동기 callback 예시
function requestServer() {
var result;
$.get("http://dq.com/test.jsp?name=ktko&age=30", function(response) {
result = response;
}); // 여기서 pending 되지 않고 바로 return으로 넘어가게 됨.
return result;
}
console.log(requestServer()); //undefined
promise
- callback과 마찬가지로 비동기 함수를 수행 시키기 위한 도구이지만, 해당 함수 안에 동기적 작업만 존재한다면 동기적으로 작동하는 함수
- 각각의 상태를 표현할 수 있다.
- 대기(Pending): 작업이 완료되지 않은 상태
- 이행(Fulfilled): 작업이 성공적으로 완료된 상태 (resolve)
- 거부(Rejected): 작업이 실패한 상태 (reject)
- then(onFulfilled, onRejected)
- Promise 객체의 상태가 이행됐을 때와 거부됐을 때의 처리를 정의하는 메소드.
- 첫 번째 매개변수는 이행된 경우를 다루는 콜백 함수
- 두 번째 매개변수는 거부된 경우를 다루는 콜백 함수
- then을 통해서도 onRejected에 대한 처리를 할 수 있으나, catch를 통해 처리하는 것이 명확하게 눈에 들어온다.
- catch(onRejected)
- Promise 객체의 상태가 거부됐을 때의 처리를 정의하는 메소드
- then() 메소드의 두 번째 매개변수로 거부 케이스를 처리하는 것과 동일한 역할
- Promise.all(iterable)
- 여러 개의 Promise 객체를 배열로 받아서 모든 Promise 객체가 이행될 때까지 기다린 후 결과를 배열로 반환하는 메소드
- Promise.race(iterable)
- 여러 개의 Promise 객체를 배열로 받아서 가장 먼저 이행된 Promise 객체의 결과를 반환하는 메소드.
- Promise.resolve(value)
- 이행된 Promise 객체를 반환
- Promise.reject(reason)
- 거부된 Promise 객체를 반환
- then, catch를 적절하게 체이닝 방식으로 코드를 작성해서 사용할 수 있다.
- then을 체이닝 방식을 통해 처리하기 위해서는 return을 통해 처리할 값을 반환해야 함
// 비동기 작업을 수행하는 함수를 Promise로 감싸는 예시
const fetchData = (url) => {
return new Promise((resolve, reject) => {
// 비동기 작업 예시: setTimeout을 사용하여 1초 후에 결과를 반환
setTimeout(() => {
if (url === 'https://example.com/data') {
resolve('Data fetched successfully');
} else {
reject('Error fetching data');
}
}, 1000);
});
};
console.log('print 1')
// Promise 사용 예시
fetchData('https://example.com/data')
.then((result) => {
console.log(result); // Data fetched successfully
})
.catch((error) => {
console.error(error); // Error fetching data
});
console.log('print 3')
// then에 체이닝을 통해 출력
const fetchData = (url) => {
return new Promise((resolve, reject) => {
// 비동기 작업 예시: setTimeout을 사용하여 1초 후에 결과를 반환
setTimeout(() => {
if (url === 'https://example.com/data') {
resolve('Data fetched successfully');
} else {
reject('Error fetching data');
}
}, 1000);
});
};
console.log('print 1')
// Promise 사용 예시
fetchData('https://example.com/data')
.then((result) => {
console.log(result); // Data fetched successfully
return result + " chaining then"
})
.then((result) => {
console.log(result); // Data fetched successfully chaining then
})
.catch((error) => {
console.error(error); // Error fetching data
});
console.log('print 3')
async/await
- 함수 앞에 async를 붙이면 해당 함수는 자동으로 Promise를 반환한다.
- Promise로 처리되는 부분에 await을 붙이면 해당 Promise가 끝날 때 까지 기다린다.
- 즉, 동기적으로 처리되어 Promise가 처리되면 결과와 함께 실행이 재개된다.
/* Rest API 코드
@GetMapping("/fetch/data")
public Map<String, String> responseData() throws InterruptedException {
HashMap<String, String> data = new HashMap<>();
data.put("data1", "DQCAT3");
data.put("data2", "DQCAT3.1");
data.put("data3", "LogLAY");
Thread.sleep(3000);
return data;
}
*/
import fetch from 'node-fetch'
function fetchApi(url) {
return fetch(url)
.then(response => {
if (!response.ok) {
throw new Error(`Network response was not ok. Status: ${response.status}`);
}
return response.json();
})
.catch(error => {
console.error('Error fetching data:', error);
});
}
function first () {
console.log("This is first func")
const apiUrl = 'http://localhost:8080/fetch/data';
let data = {}
fetchApi(apiUrl)
.then(responseData => {
data = responseData
});
console.log('first', data)
}
function second () {
console.log("This is second func")
const apiUrl = 'http://localhost:8080/fetch/data';
let data = {}
fetchApi(apiUrl)
.then(responseData => {
data = responseData
});
console.log('second', data)
}
first()
second()
console.log('\n============================================================================================================================\n')
async function firstAsync () {
console.log("This is firstAsync func")
const apiUrl = 'http://localhost:8080/fetch/data';
let data = {}
await fetchApi(apiUrl)
.then(responseData => {
data = responseData
});
console.log('firstAsync', data)
}
async function secondAsync () {
console.log("This is secondAsync func")
const apiUrl = 'http://localhost:8080/fetch/data';
let data = {}
await fetchApi(apiUrl)
.then(responseData => {
data = responseData
});
console.log('secondAsync', data)
}
firstAsync()
secondAsync()
// 혹은 아래와 같이 사용 가능
// async를 추가하면 함수는 Promise를 반환하기 때문
firstAsync().then((data) => {console.log('firstAsync', data)})
secondAsync().then((data) => {console.log('secondtAsync', data)})
// 출력
This is first func
first {}
This is second func
second {}
============================================================================================================================
This is firstAsync func
This is secondAsync func
secondAsync { data3: 'LogLAY', data2: 'DQCAT3.1', data1: 'DQCAT3' }
firstAsync { data3: 'LogLAY', data2: 'DQCAT3.1', data1: 'DQCAT3' }
728x90
'FE > JavaScript' 카테고리의 다른 글
JavaScript - JSON 데이터 변환, 추출, 원하는 데이터 찾기 (0) | 2021.12.13 |
---|---|
JavaScript - 사용자 정의 객체 Class 정의 (0) | 2021.12.13 |
JavaScript - 사용자 정의 함수 new Object() (0) | 2021.12.13 |
JavaScript - 사용자 정의 객체 생성자 함수 (function, prototype) (0) | 2021.12.13 |
JavaScript - 사용자 정의 객체 리터럴 (0) | 2021.12.13 |
Comments