mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-06 22:38:37 +08:00
Add support for ontimeout and onerror handler when using XMLHttpRequest for Android and iOS
Summary:Currently React-Native does not have `ontimeout` and `onerror` handlers for [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest). This is an extension to [No timeout on XMLHttpRequest](https://github.com/facebook/react-native/issues/4648). With addition to two handlers, both Android and iOS can now handle `ontimeout` if request times out and `onerror` when there is general network error. **Test plan** Code has been tested on both Android and iOS with [Charles](https://www.charlesproxy.com/) by setting a breakpoint on the request which fires `ontimeout` when the request waits beyond `timeout` time and `onerror` when there is network error. **Usage** JavaScript - ``` var request = new XMLHttpRequest(); function onLoad() { console.log(request.status); }; function onTimeout() { console.log('Timeout'); }; function onError() { console.log('General network error'); }; request.onload = onLoad; request.ontimeout = onTimeout; request.onerr Closes https://github.com/facebook/react-native/pull/6841 Differential Revision: D3178859 Pulled By: lexs fb-gh-sync-id: 30674570653e92ab5f7e74bd925dd5640fc862b6 fbshipit-source-id: 30674570653e92ab5f7e74bd925dd5640fc862b6
This commit is contained in:
committed by
Facebook Github Bot 9
parent
967dbd0cbe
commit
d09cd62011
@@ -15,6 +15,8 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
|
||||
import java.net.SocketTimeoutException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -172,7 +174,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
|
||||
|
||||
Headers requestHeaders = extractHeaders(headers, data);
|
||||
if (requestHeaders == null) {
|
||||
onRequestError(executorToken, requestId, "Unrecognized headers format");
|
||||
onRequestError(executorToken, requestId, "Unrecognized headers format", null);
|
||||
return;
|
||||
}
|
||||
String contentType = requestHeaders.get(CONTENT_TYPE_HEADER_NAME);
|
||||
@@ -186,7 +188,8 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
|
||||
onRequestError(
|
||||
executorToken,
|
||||
requestId,
|
||||
"Payload is set but no content-type header specified");
|
||||
"Payload is set but no content-type header specified",
|
||||
null);
|
||||
return;
|
||||
}
|
||||
String body = data.getString(REQUEST_BODY_KEY_STRING);
|
||||
@@ -194,7 +197,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
|
||||
if (RequestBodyUtil.isGzipEncoding(contentEncoding)) {
|
||||
RequestBody requestBody = RequestBodyUtil.createGzip(contentMediaType, body);
|
||||
if (requestBody == null) {
|
||||
onRequestError(executorToken, requestId, "Failed to gzip request body");
|
||||
onRequestError(executorToken, requestId, "Failed to gzip request body", null);
|
||||
return;
|
||||
}
|
||||
requestBuilder.method(method, requestBody);
|
||||
@@ -206,14 +209,15 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
|
||||
onRequestError(
|
||||
executorToken,
|
||||
requestId,
|
||||
"Payload is set but no content-type header specified");
|
||||
"Payload is set but no content-type header specified",
|
||||
null);
|
||||
return;
|
||||
}
|
||||
String uri = data.getString(REQUEST_BODY_KEY_URI);
|
||||
InputStream fileInputStream =
|
||||
RequestBodyUtil.getFileInputStream(getReactApplicationContext(), uri);
|
||||
if (fileInputStream == null) {
|
||||
onRequestError(executorToken, requestId, "Could not retrieve file for uri " + uri);
|
||||
onRequestError(executorToken, requestId, "Could not retrieve file for uri " + uri, null);
|
||||
return;
|
||||
}
|
||||
requestBuilder.method(
|
||||
@@ -242,7 +246,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
|
||||
if (mShuttingDown) {
|
||||
return;
|
||||
}
|
||||
onRequestError(executorToken, requestId, e.getMessage());
|
||||
onRequestError(executorToken, requestId, e.getMessage(), e);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -264,7 +268,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
|
||||
onRequestSuccess(executorToken, requestId);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
onRequestError(executorToken, requestId, e.getMessage());
|
||||
onRequestError(executorToken, requestId, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -294,11 +298,15 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
|
||||
getEventEmitter(ExecutorToken).emit("didReceiveNetworkData", args);
|
||||
}
|
||||
|
||||
private void onRequestError(ExecutorToken ExecutorToken, int requestId, String error) {
|
||||
private void onRequestError(ExecutorToken ExecutorToken, int requestId, String error, IOException e) {
|
||||
WritableArray args = Arguments.createArray();
|
||||
args.pushInt(requestId);
|
||||
args.pushString(error);
|
||||
|
||||
if ((e != null) && (e.getClass() == SocketTimeoutException.class)) {
|
||||
args.pushBoolean(true); // last argument is a time out boolean
|
||||
}
|
||||
|
||||
getEventEmitter(ExecutorToken).emit("didCompleteNetworkResponse", args);
|
||||
}
|
||||
|
||||
@@ -385,7 +393,8 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
|
||||
onRequestError(
|
||||
ExecutorToken,
|
||||
requestId,
|
||||
"Missing or invalid header format for FormData part.");
|
||||
"Missing or invalid header format for FormData part.",
|
||||
null);
|
||||
return null;
|
||||
}
|
||||
MediaType partContentType = null;
|
||||
@@ -405,7 +414,8 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
|
||||
onRequestError(
|
||||
ExecutorToken,
|
||||
requestId,
|
||||
"Binary FormData part needs a content-type header.");
|
||||
"Binary FormData part needs a content-type header.",
|
||||
null);
|
||||
return null;
|
||||
}
|
||||
String fileContentUriStr = bodyPart.getString(REQUEST_BODY_KEY_URI);
|
||||
@@ -415,12 +425,13 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
|
||||
onRequestError(
|
||||
ExecutorToken,
|
||||
requestId,
|
||||
"Could not retrieve file for uri " + fileContentUriStr);
|
||||
"Could not retrieve file for uri " + fileContentUriStr,
|
||||
null);
|
||||
return null;
|
||||
}
|
||||
multipartBuilder.addPart(headers, RequestBodyUtil.create(partContentType, fileInputStream));
|
||||
} else {
|
||||
onRequestError(ExecutorToken, requestId, "Unrecognized FormData part.");
|
||||
onRequestError(ExecutorToken, requestId, "Unrecognized FormData part.", null);
|
||||
}
|
||||
}
|
||||
return multipartBuilder;
|
||||
@@ -464,4 +475,4 @@ public final class NetworkingModule extends ReactContextBaseJavaModule {
|
||||
return getReactApplicationContext()
|
||||
.getJSModule(ExecutorToken, DeviceEventManagerModule.RCTDeviceEventEmitter.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user