54 msdn magazine WinJS on Windows 8.1
enumeration. Th e enumeration has seven values (in descending
order): max, high, aboveNormal, normal, belowNormal, idle and
min. Jobs of equal priority are run on a fi rst-in, fi rst-out basis.
Turning to the test case, I create a job on the Scheduler to populate
each HubSection when scheduler.html loads. For each HubSection,
I call Scheduler.schedule and pass in a function that populates the
HubSection. Th e fi rst two jobs are run at normal priority and all the
others are run when the UI thread is idle. In the third parameter for
the schedule method, thisArg, I pass in some context for the job.
The schedule method returns a
Job object, which lets me monitor a
job’s progress or cancel it. For each
job, I assign the same OwnerToken
object to its owner property. Th is
lets me cancel all scheduled jobs
attributed to that owner token.
See Figure 16.
Now when I run the HTML UI
Responsiveness diagnostics test, I
should see some diff erent results.
Figure 17 shows the results of the
second test.
During the second test, the app
dropped fewer frames over a shorter
period of time. Th e experience in
the app was better, too: the Hub
control populated more quickly
and there was almost no lag.
Web Workers
Th e standard Web platform includes
the Web Worker API that lets an app
run background tasks off the UI thread. In short, Web Workers (or
just Workers) allow for multi-threading in JavaScript applications.
You pass simple messages (a string or simple JavaScript object) to the
Worker thread and the Worker returns messages back to the main
thread using the postMessage method.
Workers run in a diff erent script context from the rest of the app, so
they can’t access the UI. You can’t create new HTML ele ments using
createElement or leverage features of third-party libraries that rely on
the document object (for example, the jQuery function—$). However,
Figure 15 Timeline Details Where the UI Thread Evaluates Scheduler.js
Figure 1 6 Updated Scheduler.js Using Scheduler API
(function () {
"use strict";
var dataRequest, jobOwnerToken;
var scheduler = WinJS.Utilities.Scheduler;
WinJS.UI.Pages.define("/pages/scheduler/scheduler.html", {
ready: function (element, options) {
performance.mark("navigated to scheduler");
dataRequest = Data.featuredCollections.
then(function (collections) {
performance.mark("got collection");
var hub = element.querySelector("#featuredHub");
if (!hub) { return; }
var hubSections = hub.winControl.sections,
hubSection, collection, priority;
jobOwnerToken = scheduler.createOwnerToken();
for (var i = 0; i < hubSections.length; i++) {
hubSection = hubSections.getItem(i);
collection = collections.getItem(i);
priority == (i < 2)? scheduler.Priority.normal :
scheduler.Priority.idle;
scheduler.schedule(function () {
populateSection(this.section, this.collection)
},
priority,
{ section: hubSection, collection: collection },
"adding hub section").
owner = jobOwnerToken;
}
});
},
unload: function () {
dataRequest && dataRequest.cancel();
jobOwnerToken && jobOwnerToken.cancelAll();
}
// Other PageControl members ...
});
function populateSection(section, collection) {
performance.mark("creating a hub section");
section.data.header = collection.data.title;
var contentElement = section.data.contentElement;
contentElement.innerHTML = "";
var pictures = collection.data.pictures;
for (var i = 0; i < 6; i++) {
$(contentElement).append("<img src='" + pictures[i].pictureThumb + "' />");
(i % 2) && $(contentElement).append("<br/>")
}
}
})();