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

Support 'hidden' trigger for visibility-v3 #8805

Merged
merged 3 commits into from Apr 19, 2017

Conversation

zhouyx
Copy link
Contributor

@zhouyx zhouyx commented Apr 18, 2017

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.

@zhouyx zhouyx requested a review from dvoytenko April 18, 2017 01:18
*/
createReportReadyPromise_() {
const viewer = this.root.getViewer();
let resolver = null;
Copy link
Contributor

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();
    }
  });
});

Copy link
Contributor Author

@zhouyx zhouyx Apr 19, 2017

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?

Copy link
Contributor

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];
Copy link
Contributor

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.

Copy link
Contributor Author

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;
Copy link
Contributor

Choose a reason for hiding this comment

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

Do this:

  1. Remember stub instance above const stub = sandbox.stub(...)
  2. In the then of this promise, check that this stub was called.

Copy link
Contributor Author

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,
Copy link
Contributor

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?

Copy link
Contributor Author

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
Copy link
Contributor

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
Copy link
Contributor

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()} */
Copy link
Contributor

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_) {
Copy link
Contributor

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_();
Copy link
Contributor

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.

Copy link
Contributor Author

@zhouyx zhouyx Apr 19, 2017

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!

@zhouyx
Copy link
Contributor Author

zhouyx commented Apr 19, 2017

@dvoytenko comments addressed


return new Promise(resolve => {
viewer.onVisibilityChanged(() => {
resolve();
Copy link
Contributor

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.

Copy link
Contributor Author

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',
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@dvoytenko
Copy link
Contributor

LGTM with a couple of additional requests.

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

3 participants