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
Support 'hidden' trigger for visibility-v3 #8805
Conversation
*/ | ||
createReportReadyPromise_() { | ||
const viewer = this.root.getViewer(); | ||
let resolver = null; |
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.
Remove let resolver
from here and move the new Promise
and recombine with the listener below. Ideally, the less we leak resolve/reject methods the better. E.g.
if (!isVisible()) {
return Promise.resolve();
}
return new Promise(resolve => {
viewer.onVisibilityChanged(() => {
if (!isVisible()) {
resolve();
}
});
});
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.
! it looks much better!
other than using extra memory, an extra line of code. Is there anything I am missing when you say leak?
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.
It's a scope leak. Sometimes it makes sense to scope resolve
outside of the promise. That communicates that a promise can be resolved several different ways. In this case the situation is simpler - only one resolution involved and thus it's better to scope it in. It's no different then defining a let
variable inside the if
if it's only used in that branch.
} | ||
let trackerProfile = EVENT_TRACKERS[eventType]; | ||
if (!trackerProfile && !isEnumValue(AnalyticsEventType, eventType)) { | ||
let trackerProfile = EVENT_TRACKERS[trackerType]; |
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.
Let's instead have new EVENT_TRACKERS['hidden']
, it should be the same as visible
, specifically it should have name = 'visible-v3'
. Then the root will reuse the same tracker for both visibile
and hidden
. But I'd like to have all trigger event types to be as separate keys of EVENT_TRACKERS
. On the plus side, you won't need trackerType
var.
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.
done
}; | ||
}); | ||
const promise = tracker.createReportReadyPromise_(); | ||
return promise; |
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.
Do this:
- Remember stub instance above
const stub = sandbox.stub(...)
- In the
then
of this promise, check that this stub was called.
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.
done
@@ -580,6 +584,7 @@ describes.realWin('Events', {amp: 1}, env => { | |||
target, | |||
matchEmptySpec, | |||
readyPromise, | |||
/* createReadyReportPromiseFunc */ null, |
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.
We also need tests to make sure we add calls with non-null createReadyReportPromiseFunc
?
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.
added a test, to check if createReadyReportPromiseFunc
is a function that return a promise when eventType is hidden-v3
.
@@ -200,14 +200,16 @@ export class VisibilityManager { | |||
* `readyPromise` is resolved, if specified. | |||
* @param {!Object<string, *>} spec | |||
* @param {?Promise} readyPromise | |||
* @param {?function()} createReportPromiseFunc |
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.
?function():!Promise
} | ||
|
||
/** | ||
* @param {!VisibilityModel} model | ||
* @param {!Object<string, *>} spec | ||
* @param {?Promise} readyPromise | ||
* @param {?function()} createReportPromiseFunc |
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.
ditto
/** @private {boolean} */ | ||
this.reportReady_ = true; | ||
|
||
/** @private {?function()} */ |
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.
ditto
this.eventResolver_(); | ||
this.eventResolver_ = null; | ||
} | ||
if (!this.reportReady_ && this.createReportReadyPromise_) { |
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.
Convert this to else if (...)
?
this.eventResolver_ = null; | ||
} | ||
if (!this.reportReady_ && this.createReportReadyPromise_) { | ||
const reportReadyPromise = this.createReportReadyPromise_(); |
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.
With the return type of function():!Promise
we wouldn't need this assert.
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.
This is exact the type checking I am looking for!
@dvoytenko comments addressed |
c4842a2
to
e12899d
Compare
|
||
return new Promise(resolve => { | ||
viewer.onVisibilityChanged(() => { | ||
resolve(); |
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.
Let's keep the check of !viewer.isVisible()
before calling resolve. It's possible that visibility changed is called many times w/o actually changing isVisible
boolean.
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.
my bad! fixed
@@ -104,6 +104,11 @@ const EVENT_TRACKERS = { | |||
allowedFor: ALLOWED_FOR_ALL, | |||
klass: VisibilityTracker, | |||
}, | |||
'hidden-v3': { | |||
name: 'visible-v3', |
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.
Let's add a comment here, e.g. // Reuse tracker with visibility
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.
done
LGTM with a couple of additional requests. |
for #8315
I went with the approach that pass in a function to generate reportReady promise. Will only generate the promise after conditionMet.
I didn't add another experimental tag for this. Can always add one if anyone feels it is necessary.
noted the viewer visible doesn't work for inabox case, and will not address it in this PR.