Quellcode durchsuchen

rn: refactor loadScript

- use AbortController for setting the fetch timeout
- use async / await syntax for clarify
- set the default timeout to 5s (previously non-existent, aka 0)
- add ability to load but not evaluate a script
master
Saúl Ibarra Corretgé vor 6 Jahren
Ursprung
Commit
35130f0736
1 geänderte Dateien mit 41 neuen und 52 gelöschten Zeilen
  1. 41
    52
      react/features/base/util/loadScript.native.js

+ 41
- 52
react/features/base/util/loadScript.native.js Datei anzeigen

@@ -1,6 +1,9 @@
1 1
 // @flow
2 2
 
3
-import { timeoutPromise } from './timeoutPromise';
3
+/**
4
+ * Default timeout for loading scripts.
5
+ */
6
+const DEFAULT_TIMEOUT = 5000;
4 7
 
5 8
 /**
6 9
  * Loads a script from a specific URL. React Native cannot load a JS
@@ -13,63 +16,49 @@ import { timeoutPromise } from './timeoutPromise';
13 16
  * @param {number} [timeout] - The timeout in millisecnods after which the
14 17
  * loading of the specified {@code url} is to be aborted/rejected (if not
15 18
  * settled yet).
19
+ * @param {boolean} skipEval - Wether we want to skip evaluating the loaded content or not.
16 20
  * @returns {void}
17 21
  */
18
-export function loadScript(url: string, timeout: ?number): Promise<void> {
19
-    return new Promise((resolve, reject) => {
20
-        // XXX The implementation of fetch on Android will throw an Exception on
21
-        // the Java side which will break the app if the URL is invalid (which
22
-        // the implementation of fetch on Android calls 'unexpected url'). In
23
-        // order to try to prevent the breakage of the app, try to fail on an
24
-        // invalid URL as soon as possible.
25
-        const { hostname, pathname, protocol } = new URL(url);
22
+export async function loadScript(
23
+        url: string, timeout: number = DEFAULT_TIMEOUT, skipEval: boolean = false): Promise<any> {
24
+    // XXX The implementation of fetch on Android will throw an Exception on
25
+    // the Java side which will break the app if the URL is invalid (which
26
+    // the implementation of fetch on Android calls 'unexpected url'). In
27
+    // order to try to prevent the breakage of the app, try to fail on an
28
+    // invalid URL as soon as possible.
29
+    const { hostname, pathname, protocol } = new URL(url);
26 30
 
27
-        // XXX The standard URL implementation should throw an Error if the
28
-        // specified URL is relative. Unfortunately, the polyfill used on
29
-        // react-native does not.
30
-        if (!hostname || !pathname || !protocol) {
31
-            reject(`unexpected url: ${url}`);
31
+    // XXX The standard URL implementation should throw an Error if the
32
+    // specified URL is relative. Unfortunately, the polyfill used on
33
+    // react-native does not.
34
+    if (!hostname || !pathname || !protocol) {
35
+        throw new Error(`unexpected url: ${url}`);
36
+    }
32 37
 
33
-            return;
34
-        }
38
+    const controller = new AbortController();
39
+    const signal = controller.signal;
35 40
 
36
-        let fetch_ = fetch(url, { method: 'GET' });
41
+    const timer = setTimeout(() => {
42
+        controller.abort();
43
+    }, timeout);
37 44
 
38
-        // The implementation of fetch provided by react-native is based on
39
-        // XMLHttpRequest. Which defines timeout as an unsigned long with
40
-        // default value 0, which means there is no timeout.
41
-        if (timeout) {
42
-            // FIXME I don't like the approach with timeoutPromise because:
43
-            //
44
-            // * It merely abandons the underlying XHR and, consequently, opens
45
-            //   us to potential issues with NetworkActivityIndicator which
46
-            //   tracks XHRs.
47
-            //
48
-            // * @paweldomas also reported that timeouts seem to be respected by
49
-            //   the XHR implementation on iOS. Given that we have
50
-            //   implementation of loadScript based on fetch and XHR (in an
51
-            //   earlier revision), I don't see why we're not using an XHR
52
-            //   directly on iOS.
53
-            //
54
-            // * The approach of timeoutPromise I found on the Internet is to
55
-            //   directly use XHR instead of fetch and abort the XHR on timeout.
56
-            //   Which may deal with the NetworkActivityIndicator at least.
57
-            fetch_ = timeoutPromise(fetch_, timeout);
58
-        }
45
+    const response = await fetch(url, { signal });
59 46
 
60
-        fetch_
61
-            .then(response => {
62
-                switch (response.status) {
63
-                case 200:
64
-                    return response.responseText || response.text();
47
+    // If the timeout hits the above will raise AbortError.
48
+
49
+    clearTimeout(timer);
50
+
51
+    switch (response.status) {
52
+    case 200: {
53
+        const txt = await response.text();
54
+
55
+        if (skipEval) {
56
+            return txt;
57
+        }
65 58
 
66
-                default:
67
-                    throw response.statusText;
68
-                }
69
-            })
70
-            .then(responseText => {
71
-                eval.call(window, responseText); // eslint-disable-line no-eval
72
-            })
73
-            .then(resolve, reject);
74
-    });
59
+        return eval.call(window, txt); // eslint-disable-line no-eval
60
+    }
61
+    default:
62
+        throw new Error(`loadScript error: ${response.statusText}`);
63
+    }
75 64
 }

Laden…
Abbrechen
Speichern