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

do not block execution when async functions are called multiple times #830

Merged
merged 3 commits into from Mar 9, 2020

Conversation

vonovak
Copy link
Member

@vonovak vonovak commented Mar 7, 2020

Summary

firstly, let me say I'm open to discussing this. There may be some issues I didn't notice.

Motivation: currently, when people call some of the functions exposed by the library (eg. signInSilently) multiple times, the first call will "get through" to the native sign in SDKs and start desired operation. The next calls, however, will get blocked while the first call in not done. The error message given in that case is:

"Cannot set promise. You've called \"" + requestedOperation + "\" while \"" + getNameOfCallInProgress() + "\" is already in progress and has not completed yet. " +
                "Make sure you're not repeatedly calling signInSilently, signIn or getTokens from your JS code while the previous call has not completed yet."

From looking at various reported issues, this sometimes seems to be problematic because I got an impression that it sometimes happens that people call some async JS function we export, let's call it f() (f can be eg. signInSilently) which calls some other function F() in the native module. F() requires some network IO and since network can be unreliable, people can try to call the same function f() again when they think it has been taking too long. This time, because F() didn't finish (maybe there is a network problem), the native module will decide not to call F() again and rejects with the error mentioned above.

This PR changes the behavior: again consider user calls f(). The native module calls F(), and when it's taking too long, user again calls f(). What happens in this PR is that the promise we're storing in the native module for the result of the first F() will get rejected and we'll store the promise from the second call. F() is then repeated without waiting for the first F() to finish.

what can happen here is

  • only first F() finishes with a delay: we'll use the promise we stored for the second call of F() and resolve/reject with result of the first F()
  • first F() does not finish but second F() does: we'll use the promise we stored for the second call of F() and resolve/reject with result of the second F()
  • both first and second F() finish: we'll use the promise we stored for the second call of F() and resolve/reject with result of the first F(). When second F() finishes, the promise is already resolved, there is nothing to be done.
  • neither finishes, or they finish unsuccessfully: in this case user can try again

It's not perfect but I hope it'll improve things, and we'll still be avoiding possible memory leaks. There certainly are alternatives, such as storing not just 1 promise in the native module, but storing all promises, or using events. Overall I think this is a a good tradeoff.

Test Plan

tested exported functions manually

What's required for testing (prerequisites)?

What are the steps to reproduce (after prerequisites)?

Compatibility

OS Implemented
iOS ✅❌
Android ✅❌

Checklist

  • I have tested this on a device and a simulator
  • I added the documentation in README.md
  • I mentioned this change in CHANGELOG.md
  • I updated the typed files (TS and Flow)
  • I added a sample use of the API in the example project (example/App.js)

@vonovak vonovak force-pushed the @vonovak/change-promise-wrapper-stategy branch from 3f7ccae to 9649cd5 Compare March 7, 2020 16:07
@vonovak vonovak requested a review from jozan March 7, 2020 16:08
@vonovak vonovak marked this pull request as ready for review March 7, 2020 16:08
@jozan
Copy link
Collaborator

jozan commented Mar 9, 2020 via email

Copy link
Collaborator

@jozan jozan left a comment

Choose a reason for hiding this comment

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

This is a good change. Makes this whole flow more readable. 👏

@jozan
Copy link
Collaborator

jozan commented Mar 9, 2020

Approved the changes! I like this approach more than the alternatives provided.

What happens for the first Javascript promise when user presses sign in button again and another promise get’s called?

@vonovak
Copy link
Member Author

vonovak commented Mar 9, 2020

@jozan the first promise will be rejected, see https://github.com/react-native-community/google-signin/blob/9649cd5305c1f9e2e11ce588c82ea5b47c8254be/android/src/main/java/co/apptailor/googlesignin/PromiseWrapper.java#L65

What happens in this PR is that the promise we're storing in the native module for the result of the first F() will get rejected and we'll store the promise from the second call.

@vonovak vonovak merged commit 3c0ed8d into master Mar 9, 2020
@vonovak vonovak deleted the @vonovak/change-promise-wrapper-stategy branch March 9, 2020 22:27
ming436534 pushed a commit to ming436534/react-native-google-signin that referenced this pull request Mar 20, 2020
* commit '85daf9693c9b78ce2ae8b56c3364f404090dc32e': (53 commits)
  Bump acorn from 5.7.3 to 5.7.4 (react-native-google-signin#838)
  4.0.0
  fix link in the docs (react-native-google-signin#832)
  do not block execution when async functions are called multiple times (react-native-google-signin#830)
  rename some apis for clarity (react-native-google-signin#829)
  rename to google-signin (react-native-google-signin#813)
  added documentation for internal app sharing (react-native-google-signin#812)
  Update android-guide.md (react-native-google-signin#811)
  Update android-guide.md
  unify troubleshooting docs (react-native-google-signin#804)
  3.0.4
  Fix flow errors (react-native-google-signin#768)
  Add community eslint config (react-native-google-signin#803)
  clarify docs for multiple openURL listeners (react-native-google-signin#802)
  Update android-guide.md
  Instructions to get configuration without Firebase (react-native-google-signin#788)
  use latest google sign in pod version
  Update android-guide.md
  3.0.3
  Move RCTPresentedViewController (react-native-google-signin#766)
  ...

# Conflicts:
#	android/src/main/java/co/apptailor/googlesignin/RNGoogleSigninModule.java
jychoi0112 added a commit to jychoi0112/google-signin that referenced this pull request Aug 8, 2020
(원본 repo의 "do not block execution when async functions are called multiple times (react-native-google-signin#830)" 에서 소스복사.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants