我正在尝试使用我的React Native Component中的fetch()
函数来处理错误的HTTP响应。我使用了here中的代码,该代码建议创建一个处理响应错误的模块。
// ApiUtils.js
var ApiUtils = {
checkStatus: function(response) {
if (response.status >= 200 && response.status < 300) {
return response;
} else {
let error = new Error(response.statusText);
error.response = response;
throw error;
}
}
};
export { ApiUtils as default };
这是我的组件的代码:
import React, { Component } from 'react';
import {View, Text, StyleSheet, Slider, ListView} from 'react-native';
import GLOBAL from "../../Globals.js"
import ApiUtils from "../utils/ApiUtils.js"
class FetchedList extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 != row2,
}),
loaded: false,
load_failed: false,
};
}
componentDidMount(){
this.fetchData();
}
fetchData(){
fetch(GLOBAL.BASE_URL + "/" + this.props.url_section + "/" + String(this.props.weekNo) + "/")
.then(ApiUtils.checkStatus)
.then((response) => {
return response.json()
})
.then((responseData) => {
if(responseData===[] || responseData.length === 0){
this.setState({
loaded: false,
load_failed: true,
});
}
else{
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData),
loaded: true,
});
}
})
.catch(function(error){
console.log("Error:" + error.message);
this.setState({load_failed: true});
})
.done();
}
render() {
if (!this.state.loaded) {
if (this.state.load_failed){
return(
<View></View>
);
}
return this.renderLoadingView();
}
else{
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderComment}
/***//>
);
}
}
renderLoadingView() {
return (
<View>
<Text>Loading . . .</Text>
</View>
);
}
renderComment(comment){
return(
<Text style={styles.row}>{comment.content}</Text>
)
}
}
const styles = StyleSheet.create({
row: {
// backgroundColor: "antiquewhite",
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
height: 50
},
});
module.exports = FetchedList
我确保测试服务器当前正在提供502网关错误。
我期望的行为是,当行.then(ApiUtils.checkStatus)
抛出错误时,它应被.catch
函数捕获,状态应由this.setState({load_failed: true});
更新。但是,我收到错误消息ExceptionsManager.js:55 this.setState is not a function
。
我发现这很奇怪,因为以下内容适用于它上面的.then( . . .)
函数:
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData),
loaded: true,
});
为什么.catch
lambda无权访问上一个函数所在的this.setState
?我能以某种方式使用.bind()
吗?
如果无法在this.setState
函数中访问catch
,如果HTTP响应不佳,如何将state.load_failed
更改为true
?
我试图将异常传递给调用函数,然后从父函数更改状态,如下所示:
我将.catch()
功能更改为:
fetchData(){
fetch(GLOBAL.BASE_URL + "/" + this.props.url_section + "/" + String(this.props.weekNo) + "/")
.then(ApiUtils.checkStatus)
.then((response) => {
return response.json()
})
.then((responseData) => {
. . .
})
.catch(function(error){
console.log("Error!");
throw error;
})
.done();
}
然后像这样更改了调用函数:
componentDidMount(){
try{
this.fetchData();
}
catch(error){
this.setState({load_failed: true});
}
console.log(this.state.load_failed);
}
然而,我得到一个简单的ExceptionsManager.js:55 Error
。
我尝试删除.done()
,但catch
阻止无法处理异常,状态不会改变,我收到警告:Possible Unhandled Promise Rejection (id: 0):
。我意识到这可能与javascript中的异步函数和传递的错误有关,但我不是百分百肯定。
环境:OSX 10.10,Android 4.1.2,React-native 0.29.2
答案 0 :(得分:5)
您的函数未按预期在相同的上下文(this
值)中运行。要解决此问题,请使用保持相同.catch(error => {
console.log("Error:" + error.message);
this.setState({load_failed: true});
})
:
bind
或明确this
到当前.catch(function(error){
console.log("Error:" + error.message);
this.setState({load_failed: true});
}.bind(this))
:
n