콜백 지옥
- JS는 싱글 스레드 환경에서 동작하는 프로그램으로, HTTP 요청을 보낸 후 백엔드가 이를 처리하는 동안에 브라우저는 아무것도 못하는 상태가 된다.
- 이를 해결하기 위해 현재 대부분의 JS 엔진은 JS 스레드 밖에서 이러한 오퍼레이션을 실행해준다. (비동기 오퍼레이션)
- 오퍼레이션이 현재 실행 중인 JS 스레드가 아니라 다른 곳에서 실행되므로, HTTP 응답을 받았다는 사실을 알려주기 위해 콜백 함수를 이용한다.
- 그러나 콜백 함수 내에서 또 다른 HTTP 요청이 발생하면, 두 번째 요청을 위한 콜백을 또 정의하는 과정에서 코드가 복잡해지는데 이것을 콜백 지옥이라고 한다.
fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
})
Promise
- Promise는 이러한 콜백 지옥을 피할 수 있는 방법 중 하나로, 함수를 실행한 후 Promise 오브젝트에서 명시된 사항들을 실행시켜주겠다는 약속을 의미한다.
const fs = require('fs');
const fsPromises = fs.promises;
fsPromises.readdir('.')
.then(files => {
console.log(files);
})
.catch(err => console.error(err));
// fsPromises.readdir이 끝나기 전에 수행
console.log("ENDED");
Pending, Resolve, Reject
function exampleFunction() {
return new Promise((resolve, reject) => {
var oReq = new XMLHttpRequest();
oReq.open("GET", "http://localhost:8080");
oReq.onload = function() {
resolve(oReq.response); // Resolve 상태
}
oReq.onerror = function() {
reject(oReq.response); // Reject 상태
}
oReq.send(); // Pending 상태
})
}
exampleFunction()
.then((r) => console.log("Rsolved"))
.cahtch((e) => console.log("Rejected"));
- pending은 오퍼레이션이 끝나기를 기다리는 상태로, 오퍼레이션이 성공적으로 끝나면 resolve() 함수를 통해 이 오퍼레이션이 성공적으로 끝났음을 알리고 원하는 값을 전달한다.
- resolve는 then의 매개변수로 넘어오는 함수를 실행한다.
- 만약 오퍼레이션 중 에러가 나는 경우 reject() 함수를 콜하고, 그 결과로 catch 매개변수로 넘어오는 함수가 실행된다.
- then이나 catch로 넘기는 함수들은 매개변수로써 해야할 일을 넘겨주기만 하고, 실제 이 함수들은 resolve와 reject가 실행되는 시점에 실행된다.
async/await
- await 연산자는 Promise를 기다리기 위해 사용되며, async function 내부에서만 사용할 수 있다.
- await 문은 Promise가 fulfill 되거나 reject 될 때까지 async 함수의 실행을 일시정지하고, Promise가 fulfill되면 async 함수를 일시정지한 부분부터 실행한다.
- 이때 await 문의 반환값은 Promise에서 fulfill된 값이 되며, 만약 Promise가 reject되면 await 문은 reject된 값을 throw 해야 한다.
const fs = require('fs');
const fsPromises = fs.promises;
async function fn() {
try {
let files = await fsPromises.readdir('.');
console.log(files);
}
catch(err) {
console.error(err);
}
}
fn(); // async 함수 이기에, 완료 전에 다음 로직이 동작
console.log("ENDED");
'Frontend' 카테고리의 다른 글
리액트 컴포넌트 (0) | 2022.03.17 |
---|---|
순수 함수와 커링 기법 (0) | 2022.03.17 |
ES6+ 문법 정리 (0) | 2022.03.17 |
react-router-dom과 로그인 인증 (0) | 2022.01.22 |
백엔드 통합과 CORS (0) | 2022.01.20 |