我正在使用React Native 0.39构建原型应用程序,该应用程序从远程源请求一些数据。要发出请求,请使用Axios.
这个电话看起来非常简单。在名为TownsList.js
的组件中,我执行
class TownsList extends Component {
constructor(props) {
super(props);
this.state = {towns: []};
}
componentDidMount() {
let url = "(SOME URL HERE)";
axios.get(url)
.then(function(response) {
// Do stuff witt the successful result
})
.catch(function (error) {
Alert.alert(
'Download failed',
'Unable to download data from '+url+"\nError:"+error,
[{text: 'OK'}])
});
...
现在奇怪的是,每当我在// Do stuff witt the successful result
块中的代码中出现其他运行时错误时 - 例如对某个常量或变量的错误引用 - 该错误将由Axios处理。错误处理程序,以及:
这感觉不对。我究竟做错了什么?我应该设置" generic"错误处理我的应用程序中的其他地方来捕获这些东西?或者这是预期的行为吗?
答案 0 :(得分:20)
如果在标记为
的块中抛出错误,这是自然行为// Do stuff witt the successful result
如果你不想要这种行为,可以考虑这样写:
axios.get(url)
.then(function(response) {
// Do stuff with the successful result
},
function (error) {
// any error from the get() will show up here
Alert.alert(
'Download failed',
'Unable to download data from '+url+"\nError:"+error,
[{text: 'OK'}])
});)
})
.catch(function(error) {
// any error from "doing stuff" will show up here
console.error(error);
})
.then()
方法允许两个函数,一个用于成功,另一个用于失败 - 原始promise的失败,而不是成功函数。
由于您自己的代码本身因某些原因而失败,您当然不想让它沉默。
答案 1 :(得分:4)
正如Malvolio所说,这是在Promise上定义catch
方法时的预期行为,抛出的所有内容都会被捕获。
对我而言,处理这种行为的最佳方法是使用Redux,因为它会将您的组件与所需数据之间的关注分开。即使我真的不知道你在React生态系统中的知识,并且你说它只是一个原型,我觉得最好使用这个范例,越快越好。以下是Redux背后的the motivations,值得一读。
要开始使用,您必须create a redux store,它可以由代表您所在州的小型独立分区的多个Reducer组成,以实现非常受控的访问。
您的城镇减速机可能看起来像这样,并且还允许您获得加载和错误状态:
import { handleActions } from 'redux-actions'
const initialState = {
data: [],
isLoading: false,
err: null
}
export default handleActions({
FETCHING_TOWNS: state => ({ ...state, isLoading: true })
FETCH_TOWNS_SUCCESS: (state, { payload }) => ({ data: payload, isLoading: false, err: null })
FETCH_TOWNS_ERROR: (state, { payload }) => ({ data: [], err: payload, isLoading: false })
}, initialState)
以下是使用combineReducers
创建商店的示例:
import { createStore, combineReducers, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import towns from './towns'
const reducers = combineReducers({
towns
})
const store = createStore(reducers, applyMiddleware(thunk))
export default store
要连接组件和reducer,您必须创建thunk操作(因此商店中的中间件)。 请注意,这只是使用redux处理副作用的一种方法!有多种方法可以解决这个问题,但这是以开头最简单和最常见的方式之一。
import axios from 'axios'
import { createAction } from 'redux-actions'
const fetchingTowns = createAction('FETCHING_TOWNS')
const fetchTownsError = createAction('FETCH_TOWNS_ERROR')
const fetchTownsSuccess = createAction('FETCH_TOWNS_SUCCESS')
export const fetchTowns = () => dispatch => {
dispatch(fetchingTowns())
axios.get()
.then(response => dispatch(fetchTownsSuccess(response)))
.catch(error => {
dispatch(fetchTownsError(err))
Alert.alert(
'Download failed',
`Unable to download data from ${url}\nError: ${error}`,
[{text: 'OK'}]
)
});
}
要使您的组件“连接”到您的商店,这意味着一旦其中一个道具发生变化,它们将再次渲染,您必须在您的顶层添加react-redux Provider
组件应用程序,然后您可以装饰您的组件,只获取组件所依赖的数据。
您的组件将如下所示,如果在子组件的呈现中发生错误,它将不会被Axios Promise截获,因为它已与您的Component分离。
import React from 'react'
import { View } from 'react-native'
import { connect } from 'react-redux'
@connect(state => ({
towns: state.towns.data
}), {
fetchTowns
})
class TownsList extends Component {
componentWillMount () {
this.props.fetchTowns()
}
render () {
const { towns } = this.props
return (
<View>
{towns.map(town => (
<TownComponent town={town} key={town.id}>
)}
</View>
)
}
}
我知道如果你不熟悉所有新的依赖项和它添加的配置,这可能有点令人讨厌,但我可以向你保证,从长远来看它是值得的!
答案 2 :(得分:-3)
可能有两个条件: -
1)据我所知,你在代码中的任何地方都使用try block,它在componentDidMount中找到了catch块,这就是为什么在catch块中捕获了其他错误的原因。
2)你的代码中的任何警告或错误都是漫游的,并且它被catch块捕获,所以我建议你使用带有catch块的try块或者最后尝试或者最后尝试。
像这样:try{
axios.get(url)
.then(function(response) {
// Do stuff witt the successful result
})
}
catch(function (error) {
Alert.alert(
'Download failed',
'Unable to download data from '+url+"\nError:"+error,
[{text: 'OK'}])
});