question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Fetch API breaks when turning network off and on.

See original GitHub issue

Environment

Environment: OS: Linux 4.15 Node: 8.11.1 Yarn: 1.5.1 npm: 5.6.0 Watchman: Not Found Xcode: N/A Android Studio: 3.1 AI-173.4720617

Packages: (wanted => installed) react: 16.3.1 => 16.3.1 react-native: 0.55.4 => 0.55.0

Note: This is the environment where we built RN v0.55.0 from source to reproduce the bug. Originally, we experienced the issue with RN v0.55.4 https://github.com/zulip/zulip-mobile/issues/2287

Description

On Android, calls to fetch() take several minutes after turning the internet connection off and on again. An initial bug report can be found here: https://github.com/zulip/zulip-mobile/issues/2287. The same report features a detailed comment on how to reproduce the bug in the app it was reported for.

Steps to Reproduce

The issue can be reproduced on Android with the following app:

export default class App extends Component<Props> {

  myFunction() {
    console.log("Button pressed");
    NetInfo.getConnectionInfo().then((connectionInfo) => {
      console.log('Initial, type: ' + connectionInfo.type + ', effectiveType: ' + connectionInfo.effectiveType);
    });
    fetch('https://facebook.github.io/react-native/movies.json')
    .then((response) => console.log("response", response))
    .catch((error) => {
      console.error(error);
    });
  };

  render() {
    return (
      <View style={styles.container}>
        <Button
          onPress={this.myFunction}
          title="Learn More"
          color="#841584"
          accessibilityLabel="Learn more about this purple button"
        />
      </View>
    );
  }
}

I then ran the app on an emulator, clicked the button a couple times and disabled and enabled the network with

$ adb shell svc data disable
$ adb shell svc data enable

Here is the app’s output in Chrome Dev Tools:

Button pressed
12:25:45.945 App.js:29 Initial, type: cellular, effectiveType: 4g
12:25:46.222 App.js:32 response Response {type: "default", status: 200, ok: true, statusText: undefined, headers: Headers, …}
12:25:53.044 App.js:27 Button pressed
12:25:53.053 App.js:29 Initial, type: none, effectiveType: unknown
12:25:58.261 App.js:27 Button pressed
12:25:58.267 App.js:29 Initial, type: cellular, effectiveType: 4g
12:35:46.703 App.js:32 response Response {type: "default", status: 200, ok: true, statusText: undefined, headers: Headers, …}
12:35:46.741 App.js:32 response Response {type: "default", status: 200, ok: true, statusText: undefined, headers: Headers, …}

Two things are interesting about the output above.

  • After turning the network off and on and pressing the button, fetch does not receive the resource.
  • After waiting for ~10 minutes, two responses come in. One is probably for the request sent out while the app was offline, and the other for the request sent out after the app was brought back online.

I also wrote a little app in Android Studio that uses two buttons and OkHttp to reproduce the issue. Reproduction steps can be found in the repo’s README.md. https://github.com/roberthoenig/react-native-fetch-bug

Expected Behavior

I expect fetch() to work the same before and after turning off and on the internet connection. In particular, I expect a prompt response to requests I send out.

Actual Behavior

After turning the internet connection off and on, fetch() did not respond promptly. It took ~10 minutes. In other trials, this varied from ~ 2 - 15 minutes. After investigating RN’s source code, I stumbled upon this line: https://github.com/facebook/react-native/blob/d52569c4a1b6bd19792e4bda23e3a8c3ac4ad8df/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java#L429

I then added

client.connectionPool().evictAll();

before it.

After adding this line, dis- and reconnecting didn’t confuse RN anymore. After reconnecting, requests just work. Oc, this is not a final solution, since client.connectionPool().evictAll(); clears all previous network connections made by this client.

A possible grand unifying theory of what is going on under the hood for this bug:

  1. I disconnect from the network.
  2. While offline, some part of the app that we have no influence on makes some network request X.
  3. X doesn’t get sent out to the internet, because we’re offline. However, the default timeout for X we have no control over is set to 0, meaning “no timeout”.
  4. I reconnect to the network.
  5. Because X never got sent out, RN will never receive a response for X. However, the timeout is set to 0, so RN will wait for X forever. Reconnecting to the network won’t change anything for X.
  6. I make my own request Y. Y gets “enqueued” by the same client that enqueued X, meaning that they’ll share the same connectionPool.
  7. X needs to be processed before Y can get processed. X blocks Y. This might be our bug.
  8. At some point in time some random event clears super old connection or something like that. X gets removed. Y gets finally dispatched, but super late.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:25
  • Comments:17 (2 by maintainers)

github_iconTop GitHub Comments

9reactions
stale[bot]commented, Nov 14, 2018

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community’s attention? This issue may be closed if no further activity occurs. You may also label this issue as “For Discussion” or “Good first issue” and I will leave it open. Thank you for your contributions.

6reactions
krtrcommented, May 24, 2019

I’m experiencing this issue still on both xhr and fetch on android react-native@0.59.8

Read more comments on GitHub >

github_iconTop Results From Across the Web

Detect Network Failures When Using Fetch | by Aaron Bruce
Fetch throws “Network request failed”​​ This error will be thrown if you attempt to issue a GET request to “google. comm” — an...
Read more >
How to Use the Fetch API (Correctly) - CODE Magazine
Navigate into the folder Samples-WebAPI and load that folder in Visual Studio Code or Visual Studio 2019. Open the appsettings.json file and ...
Read more >
Fetch API request timeout? - javascript - Stack Overflow
This causes an "Unhandled rejection" if a fetch error happens after timeout. This can be solved by handling ( .catch ) the fetch...
Read more >
iOS 13 fetch Wifi SSID is broken e… | Apple Developer Forums
application has used NEHotspotConfiguration API to configure the current Wi-Fi network. 3. application has active VPN configurations installed. - An application ...
Read more >
fetch() - Web APIs | MDN
A fetch() promise only rejects when a network error is encountered (which is usually when there's a permissions issue or similar). A fetch()...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found