0%

210129_TIL(에러 처리, Promise_1)

오늘 배운 것

에러처리

1
2
3
4
5
6
7
8
9
10
11
console.log("[Start]");

try {
foo();
} catch (error) {
console.error("[에러 발생]", error);
// [에러 발생] ReferenceError: foo is not defined
}

// 발생한 에러에 적절한 대응을 하면 프로그램이 강제 종료되지 않는다.
console.log("[End]");

에러가 발생했을 경우 강제 종료가 되는 것이 아닌 catch문을 실행 후 계속 코드를 실행시킨다.

catch (error) 에서 error에는 에러 객체가 전달된다.

옵션으로 finally 를 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
console.log("[Start]");

try {
// 실행할 코드(에러가 발생할 가능성이 있는 코드)
foo();
} catch (err) {
// try 코드 블록에서 에러가 발생하면 이 코드 블록의 코드가 실행된다.
// err에는 try 코드 블록에서 발생한 Error 객체가 전달된다.
console.error(err); // ReferenceError: foo is not defined
} finally {
// 에러 발생과 상관없이 반드시 한 번 실행된다.
console.log("finally");
}

// try...catch...finally 문으로 에러를 처리하면 프로그램이 강제 종료되지 않는다.
console.log("[End]");
1
2
3
4
5
6
7
8
9
10
11
console.log("[Start]");

try {
throw new Error("somthing wrong");
} catch (err) {
console.error(err); // Error: somthing wrong
} finally {
console.log("finally");
}

console.log("[End]");

try catch문과 throw문과 Error객체를 함께 사용할 수 있다.

에러객체는 이벤트 객체의 버블랑과 유사하게 caller 방향으로 전파된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
const foo = () => {
throw Error("foo is wrong");
};

const bar = () => {
foo();
};

try {
bar();
} catch (err) {
console.error(err); // Error: foo is wrong
}

throw된 에러를 catch하지 않으면 강제 종료된다.

콜백 방식의 비동기 처리는 콜백 함수에 caller가 없기 때문에 에러 처리가 힘들다.

1
2
3
4
5
6
7
8
try {
setTimeout(() => {
throw new Error("Error!");
}, 1000);
} catch (e) {
// 에러를 캐치하지 못한다
console.error("캐치한 에러", e);
}

이미 setTimeout의 콜백함수가 테스크 큐에서 디큐되어 콜스택에서 실행될 때는 setTimeout 함수는 콜스택에 없기 때문에 콜백함수의 caller가 콜스택 내부에 없다. 이러한 이유로 비동기 함수에서 에러처리는 에러가 났을 때 실행할 콜백함수를 인수로 줬었다.

Promise

비동기 함수는 로직 안에 비동기로 동작하는 코드가 있다면 그 함수는 비동기 함수이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>

<body>
<button>click</button>
<script>
document.onclick = () => {
console.log("click me!");
return "click me";
};
</script>
</body>
</html>

이벤트 핸들러는 비동기로 동작하기 때문에 return 값이 의미가 없다.

이러한 이유 때문에 비동기 함수는 콜백함수를 이용하여 값을 전달 받았다. 하지만 콜백 함수를 이용하면 콜백헬 또는 에러 처리에 대한 어려움 등이 있다. 이와 같은 이유로 프로미스가 등장했다.

프로미스의 생성

1
2
3
4
5
6
7
8
9
// 프로미스 생성
const promise = new Promise((resolve, reject) => {
// Promise 함수의 콜백 함수 내부에서 비동기 처리를 수행한다.
if (/* 비동기 처리 성공 */) {
resolve('result');
} else { /* 비동기 처리 실패 */
reject('failure reason');
}
});

resolve의 인수값으로는 성공했을 시의 처리 reject의 인수값으로는 실패했을 시의 처리값을 인수로 준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const get = (url) => {
const xhr = new XMLHttpRequest();

xhr.open("GET", url);
// xhr.setRequestHeader('content-type', 'application/json');
xhr.send();

xhr.onload = () => {
if (xhr.status === 200 || xhr.status === 201) {
console.log(JSON.parse(xhr.response));
} else {
console.error(xhr.status);
}
};
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const get = (url) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();

xhr.open("GET", url);
xhr.send();

xhr.onload = () => {
if (xhr.status === 200 || xhr.status === 201) {
// success
resolve(JSON.parse(xhr.response));
} else {
// failure
reject(xhr.status);
}
};
});
};

get("https://jsonplaceholder.typicode.com/todos/1")
.then(console.log)
.catch(console.error);

pending 상태인 프로미스에서 resolve를 호출하면 fulfilled 상태가 되고 reject를 호출하면 reject 상태가 된다.

Nyong’s GitHub