bdfgdfg
[Javascript] 비동기 fetch, promise, async, await 본문
[Javascript] 비동기 fetch, promise, async, await
marmelo12 2023. 11. 4. 00:08자바스크립트의 비동기 처리방식
자바스크립트는 기본적으로 싱글쓰레드기반의 언어.
그렇기에 비동기 작업을 요청하고, 작업이 완료되어 콜백함수등의 처리를 할 때 별도의 쓰레드가 등장해 작업을 처리하는게 아닌, 하나의 쓰레드가 모든 작업을 처리하게 된다.
-> 요청한 비동기 작업자체는 외부에서 처리는 하지만 그 결과를 받고, 어떻게 처리할지는 자바스크립트의 쓰레드가 담당.
-> 이는 동시성 문제를 고려하지 않아도 된다는 장점이 있음.
-> 또한 자바스크립트에서 비동기방식의 처리는 새로고침없이 데이터를 읽어올 수 있음.
- Call Stack: 자바스크립트의 쓰레드가 가진 스택영역
- Web API: 웹 브라우저에서 제공하는 API로 AJAX나 Timeout등의 비동기 작업을 실행
- Task Queue: Callback Queue라고도 하며 Web API에서 넘겨받은 Callback함수를 저장
- Event Loop: 주기적으로 Call Stack을 확인하고 call stack이 비었다면 Task Queue(비동기 결과)의 작업을 Call Stack으로 옮김
위 개념의 이해와 비동기(요청한 순서대로 결과가 순차적이지x, 완료된 결과는 콜백등으로 확인, 비동기 처리 자체는 보통 외부에맡김등)의 특징을 이해한다면 fetch, promise, async, await은 간단하다.
Promise
Promise는 비동기 작업을 좀 더 편리하게 처리할 수 있는 문법.
-> 완료처리(콜백함수)에서 후속으로 이어지는 비동기 작업을 처리하기도 편리하다.(then)
보통의 비동기작업은 아래와 같은데.
// callback은 하나의 정수형 인자를 받는 함수를 받음.
function increaseAndPrint(n, callback) {
setTimeout(() => {
const increased = n + 1;
console.log(increased);
if (callback) {
callback(increased);
}
}, 1000);
}
increaseAndPrint(0, (n) => {
increaseAndPrint(n, (n) => {
increaseAndPrint(n, (n) => {
increaseAndPrint(n, (n) => {
console.log("완료");
})
})
})
});
비동기 작업을 처리할수록 들여쓰기 레벨도 높아지며, 가독성또한 좋지않다.
Promise를 쓴다고해서 위 코드와 다르게 동작한다거나 하지는 않지만 훨씬 가독성 좋게 읽힐 수 있는 코드 작성이 가능.
위 코드를 Promise코드로 바꾸면 다음과 같다.
function promiseIncAndPrint(n) {
return new Promise((resolve, reject) => {
window.setTimeout(() => {
const increase = n + 1;
console.log(increase);
resolve(increase); // resolve에는 완료된 결과를 전달가능. reject는 그 반대.
},1000);
})
}
promiseIncAndPrint(0)
.then((result) => {
return promiseIncAndPrint(result);
})
.then((result) => {
return promiseIncAndPrint(result);
})
.then((result) => {
return promiseIncAndPrint(result);
})
.then((result) => {
return promiseIncAndPrint(result);
})
.then((result) => {
return promiseIncAndPrint(result);
})
.then((result) => {
console.log("끝." + result);
})
.catch((reject) => {
console.log("에러 : ", reject);
})
좀 더 깔끔한(?) 코드 작성이 가능해졌다.
Promise에는 다음과 같은 상태가 존재하는데 비동기에 익숙하다면 항상 비슷한 용어들이니 짚고넘어가자
- pending(대기): fulfilled(이행)도 rejected(거절)도 아닌, 작업중인 상태.
- fulfilled(이행): 비동기 작업이 완료된 상태, 정상적인 결과값을 반환
- rejected(실패): 비동기 작업에 실패한 상태, 에러사유를 담아서 반환.
그리고 then의 반환형도 Promise임.
Fetch
fetch는 HTTP 파이프라인을 구성하는 요청과 응답 등의 요소를 JavaScript에서 접근하고 조작할 수 있는 인터페이스를 제공. ajax 기법중 하나임. (ajax는 서버와 브라우저가 비동기방식으로 데이터를 교환하는 기능)
-> 비동기 요청 API이며 반환값은 HttpResponse객체(Promise로 처리되어 resolve에 담긴값.) 그렇기에 then 체인과 묶여서 사용됨.
let url = "https://api.odcloud.kr/api/15077586/v1/centers?page=1&perPage=284&serviceKey=대충키";
// 해당 API는 요청시 Json데이터를 응답.
fetch(url)
.then(resolve => {
return resolve.json(); // 응답데이터인 json을 js의 객체(object)로 변환.
})
.then(result => {
result.data.forEach((data) => {
console.log(data);
});
})
공공기관의 코로나 예방접종센터 정보를 알 수 있는 api를 호출해서 얻어왔고 결과는 다음과 같음.
기존 제이쿼리를 사용하지않고 XMLHttpRequest객체를 통한 방법보다 훨씬 편리한 방법이라는게 장점.
async, await
async,await은 비동기의 결과처리인 콜백방식, Promise(fetch등)과 동일하게 비동기 결과를 어떻게 처리하는지에 관한 문법.
-> Promise와 같이 비동기 결과 처리에 관해 가독성향상이 목적인듯한 문법.
-> Promise를 반환해야하만 await이 정상적으로 동작한다.
function promiseRandValue() {
return new Promise((resolve, reject) => {
window.setTimeout(() => {
resolve(Math.floor(Math.random() * (10) + 1)); // resolve에는 완료된 결과를 전달가능. reject는 그 반대.
},5000);
})
}
async function getValue() {
let value = await promiseRandValue(); // 여기라인에서 5초를 기다렸다 다음라인실행.
console.log(value);
}
getValue();
console.log('async함수 호출한쪽은 쭉 이어서 처리됨.');
위와 같이 async await을 사용하면 실제 동기방식(결과는 그자리에서 확인 및 blocking등)처럼 처리가 가능하다.
-> 여기서 중요한건 해당 async함수내에서만 그렇게 동작한다는거다.
-> 이건 fetch,then도 동일. fetch의 Promise결과를 then이 받아들이고, then안에서 Promise를 반환할 때 비동기 결과가 완료될 시 다음 then이 순서대로 동기방식과 같이 이어 받는것처럼.
사용방법은 async키워드는 function앞에 붙어서 사용되고, await키워드는 비동기 함수 앞에다 위치한다.
-> await키워드는 비동기 함수 및 프로미스를 반환하는 함수에 위치가 가능.
-> 또한 async키워드가 붙은 function 내부안이어야만 한다.
'웹프로그래밍 > HTML_CSS_Javascript 기초' 카테고리의 다른 글
[Javascript] DOM(Document Object Model) (0) | 2023.11.05 |
---|---|
자바스크립트의 스코프 레벨,스코프 체인,클로져 (0) | 2023.09.12 |
CSS 정리 (0) | 2023.09.10 |
요소(element)와 컨테이너(container) (0) | 2023.09.09 |
VS 코드 익스텐션 유용한것들 (0) | 2023.09.09 |