Mat*_*one 7 asynchronous promise reactjs redux redux-thunk
我有一个基于Redux文档的基本的thunk动作创建者和减速器:http : //redux.js.org/docs/advanced/AsyncActions.html
// action creator
function fetchPosts () {
return dispatch => {
dispatch({ type: 'FETCH_POSTS_REQUEST' })
return fetch('http://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(json => dispatch({ type: 'FETCH_POSTS_SUCCESS', items: json }))
// THIS CATCHES FETCH REQUEST ERRORS, AND COMPONENT LEVEL ERRORS
.catch(error => dispatch({ type: 'FETCH_POSTS_FAILURE', error: error.message }))
}
}
// reducer
function reducer (state = { isFetching: false, items: [] }, action) {
switch (action.type) {
case 'FETCH_POSTS_REQUEST':
return Object.assign({}, state, { isFetching: true })
case 'FETCH_POSTS_SUCCESS':
return Object.assign({}, state, { isFetching: false, items: action.items })
case 'FETCH_POSTS_FAILURE':
return Object.assign({}, state, { isFetching: false })
default:
return state
}
}
Run Code Online (Sandbox Code Playgroud)
在以状态传递为道具的React组件中,我检查发布项的存在,如果存在则强制执行组件级错误:
const Test = props => {
if (!props.items.length) return null
throw new Error('Error!')
}
Run Code Online (Sandbox Code Playgroud)
启动应用程序时:
fetchPosts
动作创建者称为props.invalidProperty.error
Cannot read property 'error' of undefined
到目前为止,一切都很好。
问题是该组件的JS异常永远不会输出到控制台。取而代之的是,catch()
用于获取承诺的块会捕获错误,并调度一个FETCH_POSTS_FAILURE操作。
这样可以吞下受更新存储影响的组件中的所有错误。一个FETCH_POSTS_FAILURE状态变化被分派,但这种感觉不正确-没有错误实际上获取的职位,但在使用这些职位的分量的误差下游。
我正在寻找一种模式,以帮助将异步请求中的错误与通过调度更改状态而发生的任何其他随机错误区分开。
编辑:
Redux github回购中带有异步示例的示例:https : //github.com/nandastone/redux/commit/88ab48040ce41c39d8daba8cc0c13a6f32c38adf#diff-eeb827d44ad03655e63b7e9319a03dd4R6
一个Promise.catch
处理程序还可以捕获来自该决议或拒绝处理出现的任何错误。
fetch('http://jsonplaceholder.typicode.com/posts').then(res => {
throw new Error();
}).catch(err => {
//will handle errors from both the fetch call and the error from the resolution handler
});
Run Code Online (Sandbox Code Playgroud)
要仅处理来自的错误fetch
并确保dispatch({ type: 'FETCH_POSTS_SUCCESS', items: json })
解析处理程序中的调用引发的任何错误均未捕获到该catch
处理程序中,请将拒绝处理程序附加到fetch
。
return fetch('http://jsonplaceholder.typicode.com/posts').then(response => response.json, error => {
dispatch({ type: 'FETCH_POSTS_FAILURE', error: error.message });
}).then(json => dispatch({ type: 'FETCH_POSTS_SUCCESS', items: json }), error => {
//response body couldn't be parsed as JSON
});
Run Code Online (Sandbox Code Playgroud)
fetch
不会将状态代码> = 400视为错误,因此仅在出现网络或CORS错误时才会拒绝上述调用,这就是为什么必须在解析处理程序中检查状态代码的原因。
function fetchHandler(res) {
if (res.status >= 400 && res.status < 600) {
return Promise.reject(res);
}
return res.json();
}
return fetch('http://jsonplaceholder.typicode.com/posts').then(fetchHandler, error => {
//network error
dispatch({ type: 'NETWORK_FAILURE', error });
}).then(json => dispatch({ type: 'FETCH_POSTS_SUCCESS', items: json }), error => {
dispatch({ type: 'FETCH_POSTS_FAILURE', error: error.message });
});
Run Code Online (Sandbox Code Playgroud)
请注意,React组件中引发的任何错误都可render
能使React处于不一致状态,从而防止后续事件并使应用程序对UI事件无响应。React Fiber通过错误边界解决了这个问题。
您可以考虑将错误处理程序移动到前一个then
块中。
我写了一个简单的原理演示:https://codepen.io/anon/pen/gWzOVX?editors=0011
const fetch = () => new Promise((resolve) => {
setTimeout(resolve, 100);
});
const fetchError = () => new Promise((resolve, reject) => {
setTimeout(reject, 200)
});
fetch()
.then(() => { throw new Error("error") })
.catch(() => { console.log("error in handler caught") })
fetch()
.then(() => { throw new Error("error") },
() => { console.log("error in handler not caught") })
fetchError()
.then(() => { throw new Error("error") })
.catch(() => { console.log("error in fetch caught 1") })
fetchError()
.then(() => { throw new Error("error") },
() => { console.log("error in fetch caught 2") })
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7916 次 |
最近记录: |