https://redux-saga.js.org/docs/basics/ErrorHandling
Error Handling | Redux-Saga
Error handling
redux-saga.js.org
본 글은 리덕스 사가 공식문서를 번역한 글입니다.(*주의 : 필자의 의역이 섞여있습니다. )
In this section we'll see how to handle the failure case from the previous example.
Let's suppose that our API function Api.fetch returns a Promise which gets rejected when the remote fetch fails for some reason.
We want to handle those errors inside our Saga by dispatching a PRODUCTS_REQUEST_FAILED action to the Store.
We can catch errors inside the Saga using the familiar try/catch syntax.
이번 섹션에서는 , 전에 다루었던 예시와 함께 실패하는 케이스를 어떻게 다루는지 살펴볼 것입니다.
한번 가정을 해보겠습니다. 우리가 만든 Api.fetch 함수가 몇몇의 이유로 인해서 거절당한 프로미스를 반환하는 상황인 것입니다.
그리고 우리는 그런 에러들을 우리가 만든 사가안에서 제어하기를 원하는 상황입니다.
PRODUCTS_REQUEST_FAILED라는 액션을 스토어에 디스패치하는 행위를 통해서 말이죠.
우리는 try/ catch문이라는 익숙한 문법을 사가안에서 사용함으로써, 에러를 잡아낼 수 있습니다.
import Api from './path/to/api'
import { call, put } from 'redux-saga/effects'
// ...
function* fetchProducts() {
try {
const products = yield call(Api.fetch, '/products')
yield put({ type: 'PRODUCTS_RECEIVED', products })
}
catch(error) {
yield put({ type: 'PRODUCTS_REQUEST_FAILED', error })
}
}
(try문에 성공했을 때, 사용할 함수와 디스패치 액션, catch문에 실패했을 때 사용할 디스패치 액션을 담고 있습니다.)
In order to test the failure case, we'll use the throw method of the Generator
실패하는 케이스를 테스트하기 위해서, 우리는 제네레이터의 throw 메서드를 사용할 것입니다.
import { call, put } from 'redux-saga/effects'
import Api from '...'
const iterator = fetchProducts()
// expects a call instruction
assert.deepEqual(
iterator.next().value,
call(Api.fetch, '/products'),
"fetchProducts should yield an Effect call(Api.fetch, './products')"
)
// create a fake error
const error = {}
// expects a dispatch instruction
assert.deepEqual(
iterator.throw(error).value,
put({ type: 'PRODUCTS_REQUEST_FAILED', error }),
"fetchProducts should yield an Effect put({ type: 'PRODUCTS_REQUEST_FAILED', error })"
)
In this case, we're passing the throw method a fake error.
This will cause the Generator to break the current flow and execute the catch block.
Of course, you're not forced to handle your API errors inside try/catch blocks.
You can also make your API service return a normal value with some error flag on it.
For example, you can catch Promise rejections and map them to an object with an error field.
이 케이스에서, 우리는 가짜 에러를 throw 메서드에 주입하고 있습니다.
이것은 제네레이터에게 주의를 줄 것입니다.
어떤 주의를 주냐면, 현재의 흐름을 멈추고, catch 블록에 있는 것들을 수행하라는 주의를 주는 것입니다.
당연히, api에러를 try/catch 블록 안에서 강제하는 것은 아닙니다.
또한 api 서비스가 일반적인 값을 몇몇 에러표시와 함께 반환하도록 할 수 있습니다.
예를 들자면, 너는 프로미스 거절을 받아내고, 그것들을 에러필드 객체들과 함께 매핑할 수 있습니다.
import Api from './path/to/api'
import { call, put } from 'redux-saga/effects'
function fetchProductsApi() {
return Api.fetch('/products')
.then(response => ({ response }))
.catch(error => ({ error }))
}
function* fetchProducts() {
const { response, error } = yield call(fetchProductsApi)
if (response)
yield put({ type: 'PRODUCTS_RECEIVED', products: response })
else
yield put({ type: 'PRODUCTS_REQUEST_FAILED', error })
}
onError hook#
Errors in forked tasks bubble up to their parents until it is caught or reaches the root saga.
If an error propagates to the root saga the whole saga tree is already terminated.
The preferred approach, in this case, to use onError hook to report an exception,
inform a user about the problem and gracefully terminate your app.
Why can't I use onError hook as a global error handler?
Usually, there is no one-size-fits-all solution, as exceptions are context dependent.
Consider onError hook as the last resort that helps you to handle unexpected errors.
What if I don't want an error to bubble? Consider to use safe wrapper. You can find examples here
Consider adding `safe` effect wrapper · Issue #1250 · redux-saga/redux-saga
If somebody wants to work in it - let me know. We can then establish how this would work
github.com
분기되어 있는 에러들은 그들의 부모에게 버블링됩니다. 이것이 루트사가에 도달하기까지.
만약에 에러가 루트사가에 전달되었다면, 전체적인 사가트리는 이미 종료되어 있을 것입니다.
이 경우, 예외를 리포트하기 위해서 선호되는 접근법은 에러훅을 사용하는 것입니다.
유저에게 문제를 알리고, app을 종료하는 것입니다.
onError hook을 전역차원의 오류 처리기로 사용할 수 없는 이유는 무엇일까요?
예외는 상황에 따라 달라지기 때문에 일반적으로 사용할 수 있는 만능 해결책은 없는 것입니다.
onError hook을 예기치 않은 오류를 처리하는 데 도움이 되는 마지막 수단으로 고려하시면 되겠습니다.
에러가 거품이 끼지 않게 하려면 어떻게 해야 하냐고 물으신다면, 안전한 포장지 사용을 고려하시면 되겠습니다. 그 예는 여기서 찾을 수 있습니다.
'React > REDUX' 카테고리의 다른 글
[리덕스 사가 공식문서 번역] takeEvery이펙트와 takeLast 이펙트의 차이 (0) | 2021.10.31 |
---|---|
[리덕스 사가 공식문서번역] 이팩트에 대한 일반적인 추상화 / A common abstraction: Effect (0) | 2021.10.30 |
[리덕스사가 공식문서 번역] 액션을 스토어에 디스패치하는 방법(Dispatching actions to the store) (0) | 2021.10.30 |