fetch('http://nero-zou.com/test', {
method: 'GET'
}).then(function(response) {
//获取数据,数据处理
}).catch(function(err) {
//错误处理
});
let param = {user:'xxx',phone:'xxxxxx'};
fetch(url, {
method: 'post',
body: JSON.stringify(param)
}).then(function(response) {
//获取数据,数据处理
});
try {
fetch(url, {
method: 'post',
body: JSON.stringify(param)
}).then(function(response) {
//获取数据,数据处理
});
} catch(e) {
//捕获异常消息
}
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) {
//捕获异常消息
}
这样就大功告成了,下面是遇到的常见问题
将header里面的Content-Type 设置为’application/x-www-form-urlencoded’,如果还是报错问server 端参数是什么格式 ,然后设置Content-Type的值即可.
上述封装容易出现的问题在 response.json() 这一句中,如果response==null就会抛出异常,建议先判断response是否为null,如果为null 再进行特殊处理。
fetch 本身目前没有设置超时时间的属性,只能机制来进行设置。fetch函数在各个平台的实现,如果你看到源代码的话肯定会觉得能设置超时而且很容易,但是它封装的时候并没有把 这个作为一个属性来设置.因此只能结合promise 机制使用setTimeout 来设置超时的时间。
SSLHandshake: Received fatal alert: certificate_expired
或者是
SSLHandshake: Remote host closed connection during handshake
…
其他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();
<key>NSAppTransportSecuritykey>
<dict>
<key>NSAllowsArbitraryLoadskey>
<true/>
dict>
肯定还是报错 ,找到React native 的networking 库,在库里面添加 NSURLSession delegate 函数处理ssl 证书认证的相关代码,设置为都为pass,你可以根据是否是debug模式 来选择是不是pass ,如果是release 版建议不要这样做。
如这个函数
//根据你自己的逻辑处理这个函数,加点判断千万别直接pass,有安全隐患,如果都pass了还不如用http省的麻烦。
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;
react native 的网络操作常用的是 fetch,经了解fetch 函数的实现在iOS 和android 平台上各自都是使用RCTNetworking 实现的。
上述第4个问题的解决就是通过看RCTNetworking源代码来解决的。
以下是实现的RCTNetworking ,仔细看是用OkHttpClient来实现的。
@ReactModule(name = "RCTNetworking", supportsWebWorkers = true)
public final class NetworkingModule extends ReactContextBaseJavaModule {
private static final String CONTENT_ENCODING_HEADER_NAME = "content-encoding";
private static final String CONTENT_TYPE_HEADER_NAME = "content-type";
private static final String REQUEST_BODY_KEY_STRING = "string";
private static final String REQUEST_BODY_KEY_URI = "uri";
private static final String REQUEST_BODY_KEY_FORMDATA = "formData";
private static final String USER_AGENT_HEADER_NAME = "user-agent";
private static final int CHUNK_TIMEOUT_NS = 100 * 1000000; // 100ms
private static final int MAX_CHUNK_SIZE_BETWEEN_FLUSHES = 8 * 1024; // 8K
private final OkHttpClient mClient;//其实内部是使用的OkHttpClient
private final ForwardingCookieHandler mCookieHandler;
private final @Nullable String mDefaultUserAgent;
private final CookieJarContainer mCookieJarContainer;
private final Set mRequestIds;
private boolean mShuttingDown;
/* package */ NetworkingModule(
ReactApplicationContext reactContext,
@Nullable String defaultUserAgent,
OkHttpClient client,
@Nullable List networkInterceptorCreators) {
super(reactContext);
if (networkInterceptorCreators != null) {
OkHttpClient.Builder clientBuilder = client.newBuilder();
for (NetworkInterceptorCreator networkInterceptorCreator : networkInterceptorCreators) {
clientBuilder.addNetworkInterceptor(networkInterceptorCreator.create());
}
client = clientBuilder.build();
}
mClient = client;
OkHttpClientProvider.replaceOkHttpClient(client);
mCookieHandler = new ForwardingCookieHandler(reactContext);
mCookieJarContainer = (CookieJarContainer) mClient.cookieJar();
mShuttingDown = false;
mDefaultUserAgent = defaultUserAgent;
mRequestIds = new HashSet<>();
}
public class OkHttpClientProvider {
// Centralized OkHttpClient for all networking requests.
private static @Nullable OkHttpClient sClient;
public static OkHttpClient getOkHttpClient() {
if (sClient == null) {
//sClient = createClient();
sClient=createClient_initNetworkConfig();
}
return sClient;
}
// okhttp3 OkHttpClient is immutable
// This allows app to init an OkHttpClient with custom settings.
public static void replaceOkHttpClient(OkHttpClient client) {
sClient = client;
}
private static OkHttpClient createClient() {
// No timeouts by default
return new OkHttpClient.Builder()
.connectTimeout(0, TimeUnit.MILLISECONDS)
.readTimeout(0, TimeUnit.MILLISECONDS)
.writeTimeout(0, TimeUnit.MILLISECONDS)
.cookieJar(new ReactCookieJarContainer())
.build();
}
通过上述代码你可以发现超时可以设置,但是fetch 没有封装该属性。
RCTNetInfo 类实现的功能:查询是否联网 是否是WiFi 。
RCTNetworking类实现的功能:跟AFNetworking的实现差不多,你可以仔细研究一下。
暂时略。
执行命令react-native init ZXJNetDemo
新建文件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 (
this .state.isLoading} />
this .sendTestRequest.bind(this)}>
测试网络
{this.state.resultJson}
);
}
}
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);