-
Notifications
You must be signed in to change notification settings - Fork 43
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
Call execute after load if execute was called before ready #97
base: master
Are you sure you want to change the base?
Conversation
Why not use |
Do you mean the parent can call execute in onLoad? They absolutely can, but like I said it seems surprising that the component doesn't do this already, and it's very unlikely the caller would not want this to happen. |
@ZhangYiJiang could you provide tests here to illustrate what is expected? |
…tcha into fix-execute-race
Sure, added a test case that fails on master. It's a bit weird because we need the global hcaptcha not to be defined when the component is mounted to simulate the script loading after the component is mounted, so this is the best I can do
|
I'm done with #91, and I don't see why it shouldn't be compatible now. |
This returns Fixing this is a bit tricky - you'll probably need something like this executeAsync() {
if (!isApiReady) {
if (this.executePromise == null) {
this.executePromise = new Promise((resolve) => {
this.resolveExecutePromise = resolve;
});
}
// This means all calls before isApiReady will resolve to the same token -
// I assume this is okay, but if it is not we can store an array of promises instead
return this.executePromise;
}
// ...
}
handleOnLoad() {
// ...
if (this.resolveExecutePromise != null) {
resolveExecutePromise(this.executeAsync());
}
} Also FWIW given that the only place async is used is here https://github.com/hCaptcha/react-hcaptcha/pull/91/files#diff-bfe9874d239014961b1ae4e89875a6155667db834a410aaaa2ebe3cf89820556R207, which just returns a promise directly, it's might be better to just not add regenerator |
if (this.executeOnLoad) { | ||
this.execute(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are going to want to reset the this.executeOnLoad
after you call this.execute
.
@ZhangYiJiang You could create a new promise that is returned and then when execute does get called you can resolve when that actual promise is resolved. |
@ZhangYiJiang should we still try to implement this PR, what do you think? |
Hi @ZhangYiJiang looks like I encountered a similar issue as you are trying to solve here. Can you have a look and see if this PR solves the one here? |
No that's not quite the same issue - this is calling execute before load, that is calling execute on load. That said, since #91 is merged, this also needs to handle the async case. If |
The component has a race condition where if
execute()
is called before the API is loaded,execute
will just fail silently. The fix is to add a flag which we check on load, and calls execute again once the API is loaded if the parent had previously called it. The caller could implement the same fix we are implementing here but it is easier if the component just took care of it automatically. This PR is not compatible with #91