Add support for cancelling fetch requests with AbortController (#24419)
Summary: This adds https://github.com/mysticatea/abort-controller to polyfill [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController). This is used to cancel requests when using `fetch`. This also updates `event-target-shim` to 5.0 to make sure we only have one version of this dependency. This updates required adding a polyfill for `console.assert` which is used by the new version. I made one based on https://github.com/gskinner/console-polyfill/blob/master/console.js#L74. The polyfill is very small, especially since we already use `event-target-shim` so I think it makes sense to include in core. Depends on #24418 so that the fetch polyfill supports the `signal` parameter. Fixes #18115 [General] [Added] - Add support for cancelling fetch requests with AbortController Pull Request resolved: https://github.com/facebook/react-native/pull/24419 Differential Revision: D14912858 Pulled By: cpojer fbshipit-source-id: 8a6402910398db51e2f3e3262f07aabdf68fcf72
This commit is contained in:
Родитель
5e44c08fa5
Коммит
5e36b0c6eb
|
@ -30,3 +30,11 @@ polyfillGlobal('File', () => require('File'));
|
|||
polyfillGlobal('FileReader', () => require('FileReader'));
|
||||
polyfillGlobal('URL', () => require('URL').URL); // flowlint-line untyped-import:off
|
||||
polyfillGlobal('URLSearchParams', () => require('URL').URLSearchParams); // flowlint-line untyped-import:off
|
||||
polyfillGlobal(
|
||||
'AbortController',
|
||||
() => require('abort-controller/dist/abort-controller').AbortController, // flowlint-line untyped-import:off
|
||||
);
|
||||
polyfillGlobal(
|
||||
'AbortSignal',
|
||||
() => require('abort-controller/dist/abort-controller').AbortSignal, // flowlint-line untyped-import:off
|
||||
);
|
||||
|
|
|
@ -519,6 +519,12 @@ function consoleGroupEndPolyfill() {
|
|||
global.nativeLoggingHook(groupFormat(GROUP_CLOSE), LOG_LEVELS.info);
|
||||
}
|
||||
|
||||
function consoleAssertPolyfill(expression, label) {
|
||||
if (!expression) {
|
||||
global.nativeLoggingHook('Assertion failed: ' + label, LOG_LEVELS.error);
|
||||
}
|
||||
}
|
||||
|
||||
if (global.nativeLoggingHook) {
|
||||
const originalConsole = global.console;
|
||||
// Preserve the original `console` as `originalConsole`
|
||||
|
@ -540,6 +546,7 @@ if (global.nativeLoggingHook) {
|
|||
group: consoleGroupPolyfill,
|
||||
groupEnd: consoleGroupEndPolyfill,
|
||||
groupCollapsed: consoleGroupCollapsedPolyfill,
|
||||
assert: consoleAssertPolyfill,
|
||||
};
|
||||
|
||||
// If available, also call the original `console` method since that is
|
||||
|
@ -560,7 +567,6 @@ if (global.nativeLoggingHook) {
|
|||
// we still should pass them to original console if they are
|
||||
// supported by it.
|
||||
[
|
||||
'assert',
|
||||
'clear',
|
||||
'dir',
|
||||
'dirxml',
|
||||
|
|
|
@ -18,6 +18,7 @@ const XHRExampleFormData = require('./XHRExampleFormData');
|
|||
const XHRExampleHeaders = require('./XHRExampleHeaders');
|
||||
const XHRExampleFetch = require('./XHRExampleFetch');
|
||||
const XHRExampleOnTimeOut = require('./XHRExampleOnTimeOut');
|
||||
const XHRExampleAbortController = require('./XHRExampleAbortController');
|
||||
|
||||
exports.framework = 'React';
|
||||
exports.title = 'XMLHttpRequest';
|
||||
|
@ -61,4 +62,10 @@ exports.examples = [
|
|||
return <XHRExampleOnTimeOut />;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Abort Test',
|
||||
render() {
|
||||
return <XHRExampleAbortController />;
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const {Alert, Button, View} = require('react-native');
|
||||
|
||||
class XHRExampleAbortController extends React.Component<{}, {}> {
|
||||
_timeout: any;
|
||||
|
||||
_submit(abortDelay) {
|
||||
clearTimeout(this._timeout);
|
||||
// eslint-disable-next-line no-undef
|
||||
const abortController = new AbortController();
|
||||
fetch('https://facebook.github.io/react-native/', {
|
||||
signal: abortController.signal,
|
||||
})
|
||||
.then(res => res.text())
|
||||
.then(res => Alert.alert(res))
|
||||
.catch(err => Alert.alert(err.message));
|
||||
this._timeout = setTimeout(() => {
|
||||
abortController.abort();
|
||||
}, abortDelay);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this._timeout);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<Button
|
||||
title="Abort before response"
|
||||
onPress={() => {
|
||||
this._submit(0);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
title="Abort after response"
|
||||
onPress={() => {
|
||||
this._submit(5000);
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = XHRExampleAbortController;
|
|
@ -88,12 +88,13 @@
|
|||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"@react-native-community/cli": "^2.0.0",
|
||||
"abort-controller": "^3.0.0",
|
||||
"art": "^0.10.0",
|
||||
"base64-js": "^1.1.2",
|
||||
"connect": "^3.6.5",
|
||||
"create-react-class": "^15.6.3",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"event-target-shim": "^1.0.5",
|
||||
"event-target-shim": "^5.0.1",
|
||||
"fbjs": "^1.0.0",
|
||||
"fbjs-scripts": "^1.1.0",
|
||||
"invariant": "^2.2.4",
|
||||
|
|
15
yarn.lock
15
yarn.lock
|
@ -1176,6 +1176,13 @@ abbrev@1:
|
|||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
||||
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
|
||||
|
||||
abort-controller@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
|
||||
integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
|
||||
dependencies:
|
||||
event-target-shim "^5.0.0"
|
||||
|
||||
absolute-path@^0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/absolute-path/-/absolute-path-0.0.0.tgz#a78762fbdadfb5297be99b15d35a785b2f095bf7"
|
||||
|
@ -2744,10 +2751,10 @@ etag@~1.8.1:
|
|||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
||||
|
||||
event-target-shim@^1.0.5:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-1.1.1.tgz#a86e5ee6bdaa16054475da797ccddf0c55698491"
|
||||
integrity sha1-qG5e5r2qFgVEddp5fM3fDFVphJE=
|
||||
event-target-shim@^5.0.0, event-target-shim@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
|
||||
integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
|
||||
|
||||
eventemitter3@^3.0.0:
|
||||
version "3.1.0"
|
||||
|
|
Загрузка…
Ссылка в новой задаче