使用实例
1、使用get方式进行网络请求,例如:
fetch('http://nero-zou.com/test', {
method: 'GET'
}).then(function(response) {
//获取数据,数据处理
}).catch(function(err) {
//错误处理
});
2、使用post方式进行网络请求,例如:
let param = {user:'xxx',phone:'xxxxxx'};
fetch(url, {
method: 'post',
body: JSON.stringify(param)
}).then(function(response) {
//获取数据,数据处理
});
3、其它写法,例如:
try {
fetch(url, {
method: 'post',
body: JSON.stringify(param)
}).then(function(response) {
//获取数据,数据处理
});
} catch(e) {
//捕获异常消息
}
4、带header 或其它参数
fetch(url, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
})
})
怎样进行封装
基本上要求是写个基础的函数,其它在进行网络请求时都调用这个函数。即使以后不使用fetch直接将这个基础函数修改,不用修改其它的地方就可以实现。
基础函数的模型一般是这样的
function sendNetRequest(...props) {
this.url = props.shift(1);
this.options = props.shift(1);
return fetch(this.url, Object.assign({}, this.options))
.then((response) =>return response.json());
}
封装各个接口
//封装login 接口
function postLogin(userName,password) {
let loginParam= {user:userName,password:password};
var loginApiPort = "mlogin";//login 对应的接口
//下面的baseURL=https://XXXXX.com
return sendNetRequest(`${baseURL}/${loginApiPort}`, {
method: 'post',
body: JSON.stringify(loginParam),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
}
//...其它一系列接口的封装
调用实例
try {
postLogin(user,password)
.then((response) => {
//获取数据,数据处理
})
} catch(e) {
//捕获异常消息
}
这样就大功告成了,下面是遇到的常见问题
常见问题
1、请求时,出现异常
将header
里面的Content-Type
设置为‘application/x-www-form-urlencoded’
,如果还是报错问server端参数是什么格式 ,然后设置Content-Type
的值即可.
2、响应时,出现异常
上述封装容易出现的问题在response.json()
这一句中,如果response==null
就会抛出异常,建议先判断response
是否为null
,如果为null
再进行特殊处理。
3、fetch设置超时的时间
fetch
本身目前没有设置超时时间的属性,只能机制来进行设置。fetch
函数在各个平台的实现,如果你看到源代码的话肯定会觉得能设置超时而且很容易,但是它封装的时候并没有把 这个作为一个属性来设置.因此只能结合promise
机制使用setTimeout
来设置超时的时间。
4、https,如果server端是无效证书来进行https请求的时候出现的错误
SSLHandshake: Received fatal alert: certificate_expired
或者是
SSLHandshake: Remote host closed connection during handshake
…
(1)在android暂时无解 ,只能用http,因为它不能改变库里面的函数。如果非要支持https ,只能将你的工程目录 + node_modules/react-native/android/com/facebook/react/react-native/0.36.0/react-native-0.36.0-sources.jar!/com/facebook/react/modules/network/OkHttpClientProvider.java
,
其他rn版本的文件目录可以推测,总的来说是修改reactnative
的network
库里面的OkHttpClientProvider.Java
这个文件。OkHttpClientProvider.java
中找到下述代码
return new OkHttpClient.Builder()
.connectTimeout(0, TimeUnit.MILLISECONDS)
.readTimeout(0, TimeUnit.MILLISECONDS)
.writeTimeout(0, TimeUnit.MILLISECONDS)
.cookieJar(new ReactCookieJarContainer())
.build();
改为:
return new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory())
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true; //忽略所有的认证,直接返回了true
}
})
.connectTimeout(0, TimeUnit.MILLISECONDS)
.readTimeout(0, TimeUnit.MILLISECONDS)
.writeTimeout(0, TimeUnit.MILLISECONDS)
.cookieJar(new ReactCookieJarContainer())
.build();
(2)iOS 端 ,用xcode打开ios目录下的工程,找到infor.plist,并添加属性
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
肯定还是报错 ,找到React native的networking 库(Libraries -> RCTNetworking -> RCTHTTPRequestHandler.mm -> #pragma mark NSURLSession delegate),在库里面添加NSURLSession delegate
函数处理ssl证书认证的相关代码,设置为都为pass,你可以根据是否是debug模式来选择是不是pass ,如果是release 版建议不要这样做。
如这个函数
//根据你自己的逻辑处理这个函数,加点判断千万别直接pass,有安全隐患,如果都pass了还不如用http省的麻烦。
//只要请求的地址是HTTPS的, 就会调用这个代理方法
//challenge:质询
//NSURLAuthenticationMethodServerTrust:服务器信任
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
{
NSLog(@"%@",challenge.protectionSpace);
if (![challenge.protectionSpace.authenticationMethod isEqualToString:@"NSURLAuthenticationMethodServerTrust"]) return;
/*
NSURLSessionAuthChallengeUseCredential 使用证书
NSURLSessionAuthChallengePerformDefaultHandling 忽略证书 默认的做法
NSURLSessionAuthChallengeCancelAuthenticationChallenge 取消请求,忽略证书
NSURLSessionAuthChallengeRejectProtectionSpace 拒绝,忽略证书
*/
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
}
实例
BaseServiceApiNet.js文件
const baseURL = "https://api.app.net";
function fetchAction(...props) {
this.url = props.shift(1);
this.options = props.shift(1);
return fetch(this.url, Object.assign({}, this.options))
.then((response) =>response.json());
}
export default {
getTest() {
var apiPort = "stream/0/posts/stream/global";
return fetchAction(`${baseURL}/${apiPort}`, {
method: 'get',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
}
};
index.ios.js文件
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
ActivityIndicator
} from 'react-native';
import BaseServiceApiNet from './BaseServiceApiNet';
export default class ZXJNetDemo extends Component {
constructor(props){
super(props);
this.state ={
isLoading:false,
resultJson:null
};
}
sendTestRequest(){
if(this.state.isLoading==true){
return;
}
this.setState({
resultJson:null,
isLoading:true
});
try {
BaseServiceApiNet.getTest()
.then((response) => {
let data = response.meta;
this.setState({
resultJson:data==null?null:JSON.stringify(data),
isLoading:false
});
console.log("返回数据:"+JSON.stringify(data));
})
} catch(e) {
alert(e);
this.setState({
isLoading:false
});
}
}
render() {
return (
<View style={styles.container}>
<ActivityIndicator animating={this.state.isLoading} />
<Text style={styles.welcome} onPress={this.sendTestRequest.bind(this)}>
测试网络
</Text>
<Text style={styles.instructions}>
{this.state.resultJson}
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('ZXJNetDemo', () => ZXJNetDemo);
运行结果
参考:
http://blog.csdn.net/qq_16086969/article/details/53522980#t11
http://www.cnblogs.com/liugengqun/p/5141482.html