2017-01-01 26 views
7

我正在使用React Native 0.39构建一个原型应用程序,该应用程序从远程源请求一些数据。为了提出请求,我使用Axios.为什么我的http库的错误处理程序在应用程序中捕获所有运行时错误?

该调用看起来非常简单。在一个名为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块中在我的代码一些其他的运行时错误 - 例如不正确的套管参考了一些固定或可变 - 这个错误会由爱可信的错误处理程序处理,以及:

enter image description here

这感觉不对。我究竟做错了什么?我应该在应用程序的其他地方设置“通用”错误处理来捕捉这些东西吗?或者这是预期的行为?

+0

ary你使用try块在代码中的任何地方? – Codesingh

+0

@Codesingh不,在整个项目中搜索“try”关键字没有找到结果 –

+0

你可以在承诺里面显示代码('then') –

回答

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()方法允许两个功能,一个用于成功的哥哥呃因失败 - 原始承诺失败,而不是成功功能。

由于你自己的代码本身因为某种原因失败,你当然不想沉默。

+1

我在'.then()中做的事情是使用'setState()'更新组件的状态。被捕获的错误是我在一个子组件中发生的语法错误,它确实使用请求中的数据进行呈现。它仍然不完全直观,为什么它以这种方式工作 - 我希望库在调用成功完成时释放它的错误处理程序 - 但我想这是有道理的。 –

+1

@Pekka웃 - 你高估了图书馆区分不同类型错误的能力。承诺上下文中引发的任何异常或错误都会发生,无论是服务器错误,网络错误还是语言错误。区分它们的方法是将捕捉功能放在链条上的不同位置。 – Malvolio

-3

可以有两个条件: -

1)根据我你在任何地方使用try块中发现了catch块在componentDidMount所以这就是为什么在你的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'}]) 
     }); 
+0

你的示例代码会抛出一个错误 –

4

正如Malvolio所说,在Promise中定义catch方法时的预期行为,其中引发的所有内容都会被抓取。

对我来说,处理这种行为的最好方法是使用Redux,因为它会分离你的组件和他们需要的数据之间的关系。即使我并不真正了解你在React生态系统中的知识,并且你说它只是一个原型,我觉得最好使用这种模式,越快越好。 Redux后面有the motivations,值得一看。

要开始使用,您必须使用create a redux store,它可以由多个缩减器组成,这些缩减器将代表您的状态的小型独立分区,以允许进行非常受控制的访问。

您城镇减速可能看起来是这样,也将让你得到负荷和错误状态:

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操作(因此在商店中的中间件)。 请注意,这只是使用REDX处理副作用的一种方法!有很多方法可以解决这个问题,但这是最容易和最常见的方法之一。

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-reduxProvider组件,然后你可以装饰你的组件,只取得组件依赖的数据。

您的组件会看起来像这样,并且如果在渲染子组件时发生错误,它将不会被axios Promise拦截,因为它已从组件中分离出来。

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> 
    ) 
    } 

} 

我理解这可能是,如果你不熟悉所有的新的依赖和配置的它增加了位有点讨厌,但我可以向你保证,这是值得从长远来看!

+0

这是*真棒*!我现在正在进入Redux,仍然试图理解它,并想知道如何在我的用例中实现它。没有期望一个无辜的SO问题提供完整的自定义写作。 :)我会授予Malvolio这笔赏金并接受答案,因为他回答了字面问题,但我马上就会为此答案开始第二个答案。 (我将能够在23小时内奖励它。) –

+1

啊非常感谢!决定深入研究这个问题,我同意它可能超出你最初的问题的范围,但既然它也解决了这个问题,我认为它会好起来的,很高兴你能感激它;) –