Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed abort pending request of internetReachability #700

Merged
merged 3 commits into from Nov 29, 2023

Conversation

gizomo
Copy link
Contributor

@gizomo gizomo commented Nov 28, 2023

AbortController.abort() throws DOMException with name AbortError. This exception rejects promise with reason declared in abort function attribute as I described at #699

AbortController.abort() throws DOMException with name AbortError. This exception rejects promise with reason declared in abort function attribute.
fixed abort pending request of internetReachability
Copy link
Contributor

@mikehardy mikehardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, I have not personally played around with AbortController but this appears sane+correct based on my read of the relevant docs you helpfully linked. Thanks!

@mikehardy mikehardy added the pending merge A PR that will be merged shortly, waiting for CI or final comment label Nov 28, 2023
@mikehardy
Copy link
Contributor

Some problematic test results:

src/internal/internetReachability.ts:82:62 - error TS2322: Type 'Timeout' is not assignable to type 'void'.

82     const timeoutPromise = new Promise<Response>((): void => timeoutHandle = setTimeout(
                                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
83       (): void => controller.abort('timedout'),
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
84       this._configuration.reachabilityRequestTimeout,
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
85     ));
   ~~~~~

src/internal/internetReachability.ts:90:61 - error TS2[32](https://github.com/react-native-netinfo/react-native-netinfo/actions/runs/7016281073/job/19104478038?pr=700#step:4:33)2: Type '() => void' is not assignable to type 'void'.

90     const cancelPromise = new Promise<Response>((): void => cancel = (): void => controller.abort('canceled'));
                                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  src/internal/internetReachability.ts:90:61
    90     const cancelPromise = new Promise<Response>((): void => cancel = (): void => controller.abort('canceled'));
                                                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Did you mean to call this expression?

@mikehardy mikehardy added changes requested and removed pending merge A PR that will be merged shortly, waiting for CI or final comment labels Nov 28, 2023
@gizomo
Copy link
Contributor Author

gizomo commented Nov 29, 2023

Sorry. I hurried. I edited the file in Github. Didn't take into account return types.

@mikehardy
Copy link
Contributor

CI behaving strangely - only closing so I can reopen which typically kicks off a CI round

@mikehardy mikehardy closed this Nov 29, 2023
@mikehardy mikehardy reopened this Nov 29, 2023
@mikehardy
Copy link
Contributor

Ok - will merge and release this, it seems reasonable, please please 🙏 keep an ear out in case there are issues here, hopefully this just works for others using this functionality

@mikehardy mikehardy merged commit 0a36296 into react-native-netinfo:master Nov 29, 2023
2 checks passed
github-actions bot pushed a commit that referenced this pull request Nov 29, 2023
## [11.1.1](v11.1.0...v11.1.1) (2023-11-29)

### Bug Fixes

* internetReachability aborts handle cancel correctly ([#700](#700)) ([0a36296](0a36296))
@matt-oakes
Copy link
Collaborator

🎉 This PR is included in version 11.1.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

@Tymofiev
Copy link

@gizomo did this PR fix some real issue for you?

I am asking because it introduced one on our side because of a broken check by error message here. Since the explicit reject has been removed - abort message is 'Aborted' instead of 'timedout' | 'canceled' like expected.

cc @matt-oakes.

@mikehardy
Copy link
Contributor

@Tymofiev - Matt Oakes no longer works on the repo so cc'ing him has no effect, it's just his user account key that still does releases

Anyway, I'm listening as I was afraid this may affect others.

Is there some reason you cannot inspect on the abort reason in order to differentiate, as mentioned in the issue related to the PR?

The right way is to use abort('canceled') to set reject reason to 'canceled' instead of DOMException.

@Tymofiev
Copy link

@mikehardy I am sorry, I meant to tag you here.

It is possible to inspect on the abort reason from the signal [1], but I was wondering if we could just revert the promise reject, so no extra work required to check signal reason.

Or we could use AbortSignal.timeout [2] instead of aborting with custom string reason and then check for error messages of abort.

[1]
...
    if (signal.aborted) {
      reject(signal.reason);
    }

    // Perform the main purpose of the API
    // Call resolve(result) when done.

    // Watch for 'abort' signals
    signal.addEventListener("abort", () => {
      // Stop the main operation
      // Reject the promise with the abort reason.
      reject(signal.reason);
    });
...

[2]
...
  if (e.name === "AbortError") {
    // Notify the user of abort.
  } else if (e.name === "TimeoutError") {
    // Notify the user of timeout
...

PS: Examples taken from https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal.

@mikehardy
Copy link
Contributor

Reasonab PRs accepted but please coordinate philosophically with @gizomo

@Tymofiev
Copy link

@mikehardy yeah, okay, that's why I asked him the reason behind this change.

@gizomo
Copy link
Contributor Author

gizomo commented Dec 12, 2023

if we could just revert the promise reject, so no extra work required to check signal reason.

Using an AbortController actually cancels the fetch. Rejecting a promise is not able to cancel the fetch, that can lead to a memory leak.

I don't advocate using the 'canceled' string as a reason. We can use DOMException checking e.name === "AbortError" or more safe to check controller.signal.aborted === true

Actually, we should revert reject('canceled') after controller.abort('canceled') as an option for browsers that do not fully support AbortController API.

@Tymofiev
Copy link

Tymofiev commented Dec 12, 2023

@gizomo thanks for the quick reply. I think it would still cancel the promise if you call abort without any reason, and reject is just to make sure we can track the exact error message.

Let's revert the reject to return the previous behaviour and as you said make sure it works in case AbortController API is not supported. Does it sound good?

PS: I am all into opening new PR to do that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants