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

Use Renderer command queue to render outstream #1283

Merged
merged 2 commits into from
Jun 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 37 additions & 5 deletions src/Renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,37 @@ import { loadScript } from 'src/adloader';
import * as utils from 'src/utils';

export function Renderer(options) {
const { url, config, id, callback } = options;
const { url, config, id, callback, loaded } = options;
this.url = url;
this.config = config;
this.callback = callback;
this.handlers = {};
this.id = id;

// a renderer may push to the command queue to delay rendering until the
// render function is loaded by loadScript, at which point the the command
// queue will be processed
this.loaded = loaded;
this.cmd = [];
this.push = func => {
if (typeof func !== 'function') {
utils.logError('Commands given to Renderer.push must be wrapped in a function');
return;
}
this.loaded ? func.call() : this.cmd.push(func);
};

// bidders may override this with the `callback` property given to `install`
this.callback = callback || (() => {
this.loaded = true;
this.process();
});

// we expect to load a renderer url once only so cache the request to load script
loadScript(url, callback, true);
loadScript(url, this.callback, true);
}

Renderer.install = function({ url, config, id, callback }) {
return new Renderer({ url, config, id, callback });
Renderer.install = function({ url, config, id, callback, loaded }) {
return new Renderer({ url, config, id, callback, loaded });
};

Renderer.prototype.getConfig = function() {
Expand All @@ -36,3 +54,17 @@ Renderer.prototype.handleVideoEvent = function({ id, eventName }) {

utils.logMessage(`Prebid Renderer event for id ${id} type ${eventName}`);
};

/*
* Calls functions that were pushed to the command queue before the
* renderer was loaded by `loadScript`
*/
Renderer.prototype.process = function() {
while (this.cmd.length > 0) {
try {
this.cmd.shift().call();
} catch (error) {
utils.logError('Error processing Renderer command: ', error);
}
}
};
26 changes: 12 additions & 14 deletions src/adapters/appnexusAst.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,18 +269,17 @@ function AppnexusAstAdapter() {
}

function outstreamRender(bid) {
window.ANOutstreamVideo.renderAd({
tagId: bid.adResponse.tag_id,
sizes: [bid.getSize().split('x')],
targetId: bid.adUnitCode, // target div id to render video
uuid: bid.adResponse.uuid,
adResponse: bid.adResponse,
rendererOptions: bid.renderer.getConfig()
}, handleOutstreamRendererEvents.bind(bid));
}

function onOutstreamRendererLoaded() {
// setup code for renderer, if any
// push to render queue because ANOutstreamVideo may not be loaded yet
bid.renderer.push(() => {
window.ANOutstreamVideo.renderAd({
tagId: bid.adResponse.tag_id,
sizes: [bid.getSize().split('x')],
targetId: bid.adUnitCode, // target div id to render video
uuid: bid.adResponse.uuid,
adResponse: bid.adResponse,
rendererOptions: bid.renderer.getConfig()
}, handleOutstreamRendererEvents.bind(bid));
});
}

function handleOutstreamRendererEvents(id, eventName) {
Expand Down Expand Up @@ -313,9 +312,8 @@ function AppnexusAstAdapter() {
id: ad.renderer_id,
url: ad.renderer_url,
config: { adText: `AppNexus Outstream Video Ad via Prebid.js` },
callback: () => onOutstreamRendererLoaded.call(null, bid)
loaded: false,
});

try {
bid.renderer.setRender(outstreamRender);
} catch (err) {
Expand Down
35 changes: 35 additions & 0 deletions test/spec/renderer_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,39 @@ describe('Renderer: A renderer installed on a bid response', () => {
testRenderer1.handleVideoEvent({ id: 1, eventName: 'testEvent' });
expect(spyEventHandler.called).to.equal(true);
});

it('pushes commands to queue if renderer is not loaded', () => {
testRenderer1.push(spyRenderFn);

expect(testRenderer1.cmd.length).to.equal(1);

// clear queue for next tests
testRenderer1.cmd = [];
});

it('fires commands immediately if the renderer is loaded', () => {
const func = sinon.spy();

testRenderer1.loaded = true;
testRenderer1.push(func);

expect(testRenderer1.cmd.length).to.equal(0);
sinon.assert.calledOnce(func);
});

it('processes queue by calling each function in queue', () => {
testRenderer1.loaded = false;
const func1 = sinon.spy();
const func2 = sinon.spy();

testRenderer1.push(func1);
testRenderer1.push(func2);
expect(testRenderer1.cmd.length).to.equal(2);

testRenderer1.process();

sinon.assert.calledOnce(func1);
sinon.assert.calledOnce(func2);
expect(testRenderer1.cmd.length).to.equal(0);
});
});