原生分析的是安卓端
核心代码
//react-native/vendor/core/wehatwg-fetch.js
self.fetch = function(input, init) {
return new Promise(function(resolve, reject) {
var request = new Request(input, init);
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var options = {
status: xhr.status,
statusText: xhr.statusText,
headers: parseHeaders(xhr.getAllResponseHeaders() || ''),
};
options.url =
'responseURL' in xhr
? xhr.responseURL
: options.headers.get('X-Request-URL');
var body = 'response' in xhr ? xhr.response : xhr.responseText;
resolve(new Response(body, options));
};
xhr.onerror = function() {
reject(new TypeError('Network request failed'));
};
xhr.ontimeout = function() {
reject(new TypeError('Network request failed'));
};
xhr.open(request.method, request.url, true);
if (request.credentials === 'include') {
xhr.withCredentials = true;
} else if (request.credentials === 'omit') {
xhr.withCredentials = false;
}
request.headers.forEach(function(value, name) {
xhr.setRequestHeader(name, value);
});
xhr.send(
typeof request._bodyInit === 'undefined' ? null : request._bodyInit,
);
});
};
// node_modules/react-native/Libraries/Network/XMLHttpRequest.js
send(data: any): void {
if (this.readyState !== this.OPENED) {
throw new Error('Request has not been opened');
}
if (this._sent) {
throw new Error('Request has already been sent');
}
this._sent = true;
const incrementalEvents =
this._incrementalEvents || !!this.onreadystatechange || !!this.onprogress;
this._subscriptions.push(
RCTNetworking.addListener('didSendNetworkData', args =>
this.__didUploadProgress(...args),
),
);
this._subscriptions.push(
RCTNetworking.addListener('didReceiveNetworkResponse', args =>
this.__didReceiveResponse(...args),
),
);
this._subscriptions.push(
RCTNetworking.addListener('didReceiveNetworkData', args =>
this.__didReceiveData(...args),
),
);
this._subscriptions.push(
RCTNetworking.addListener('didReceiveNetworkIncrementalData', args =>
this.__didReceiveIncrementalData(...args),
),
);
this._subscriptions.push(
RCTNetworking.addListener('didReceiveNetworkDataProgress', args =>
this.__didReceiveDataProgress(...args),
),
);
this._subscriptions.push(
RCTNetworking.addListener('didCompleteNetworkResponse', args =>
this.__didCompleteResponse(...args),
),
);
let nativeResponseType: NativeResponseType = 'text';
if (this._responseType === 'arraybuffer') {
nativeResponseType = 'base64';
}
if (this._responseType === 'blob') {
nativeResponseType = 'blob';
}
invariant(this._method, 'Request method needs to be defined.');
invariant(this._url, 'Request URL needs to be defined.');
RCTNetworking.sendRequest(
this._method,
this._trackingName,
this._url,
this._headers,
data,
/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found
* when making Flow check .android.js files. */
nativeResponseType,
incrementalEvents,
this.timeout,
this.__didCreateRequest.bind(this),
this.withCredentials,
);
}
// node_modules/react-native/Libraries/Network/RCTNetworking.js
sendRequest(
method: string,
trackingName: string,
url: string,
headers: Object,
data: RequestBody,
responseType: 'text' | 'base64',
incrementalUpdates: boolean,
timeout: number,
callback: (requestId: number) => any,
withCredentials: boolean,
) {
const body = convertRequestBody(data);
if (body && body.formData) {
body.formData = body.formData.map(part => ({
...part,
headers: convertHeadersMapToArray(part.headers),
}));
}
const requestId = generateRequestId();
RCTNetworkingNative.sendRequest(
method,
url,
requestId,
convertHeadersMapToArray(headers),
{...body, trackingName},
responseType,
incrementalUpdates,
timeout,
withCredentials,
);
callback(requestId);
}
应用到XMLHttpRequest
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
调用流程
fetch
xhr.send -->
RCTNetworking.android.js
RCTNetworking.sendRequest -->
走到native调用到NetworkingModule
NetworkingModule.sendRequest
取消请求
XMLHttpRequest.js
abort(): void {
this._aborted = true;
if (this._requestId) {
RCTNetworking.abortRequest(this._requestId);
}
// only call onreadystatechange if there is something to abort,
// below logic is per spec
if (
!(
this.readyState === this.UNSENT ||
(this.readyState === this.OPENED && !this._sent) ||
this.readyState === this.DONE
)
) {
this._reset();
this.setReadyState(this.DONE);
}
// Reset again after, in case modified in handler
this._reset();
}