Over a million developers have joined DZone.

The WinJS Scheduler

· Mobile Zone

Visually compose APIs with easy-to-use tooling. Learn how IBM API Connect provides near-universal access to data and services both on-premises and in the cloud, brought to you in partnership with IBM.

Windows 8.1 comes with a new feature in the WinJS SDK : a scheduler. Let’s see what it is and how to use it!

In Windows 8, every job is nearly done as soon as you execute it. You could play with the msSetImmediate function but it was still a little mode “hack” than “code”.

With Windows 8.1, the SDK introduce a scheduler used by the whole WinJS framework. This scheduler helps you to define what is important (animations, visual feedback, manage user input) from what can be delayed (background work, data processing not used immediatly).

The goal is to let you build application which reacts immedialty to the user will.

What’s in it ?

Everything lives in the WinJS.Utilities.Scheduler namepsace and is written in javascript.
This namespace is often shortcuted “Scheduler” or “S” in the Microsoft samples.

var S = WinJS.Utilities.Scheduler;

There is 4 importants objects to know :

  • WinJS.Utilities.Scheduler: the main namepsace with a lot of static function which lets you start and manage jobs
  • WinJS.Utilities.Scheduler.IJob : everything thing is a job. When you start a task/work using the scheduler, it returns you an IJob object on which you can call management methods.
  • WinJS.Utilities.Scheduler.IJobInfo : information passed to your work-function when executed.
  • WinJS.Utilities.Scheduler.IOwnerToken : you want to be the owner of a task and manage a group of jobs then use this.

How to use it (101) ?

Launching a job is as simple as providing a function :

var job = WinJS.Utilities.Scheduler.schedule(function willBeExecuted(){
//work to be done

There is some optional parameters that can be set too : a priority (default is WinJS.Utilities.Scheduler.Priority.normal.), a this parameter which will be set when the function is executed and name (useful when debugging):

var whoAmI = {};
var job =  WinJS.Utilities.Scheduler.schedule(function willBeExecuted(){
//work to be done
} , WinJS.Utilities.Scheduler.Priority.normal, whoAmI, " I am the job name" );

The returned object is a IJob object and you can call some function on it to cancel it’s scheduling, pause it, resume it and have some information like the name, the priority, the owner, etc.

//create a job
var job =  WinJS.Utilities.Scheduler.schedule( /* ...*/);
//pause the job
//resume it in 5 secs
//reads the name of the job 
var name = job.name;

IJobInfo and yielding

In this case “yielding” means “let other task more important than me start and do their job while I am executing and pause me”.
Let’s assume that you have a job which takes 10 seconds to be done and that you can split it in 10 parts.
Then you can launch the job with the scheduler, do the first part and tells it : do something else (other jobs with higher priority) if necessary then call me back. The Scheduler will then manage this process for you.

When your job is executed, a parameter is actually provided and it implements the IJobInfo interface. This jobInfo object has 2 important functions and 1 important field :

  • setPromise: calling it providing a function tells the scheduler to wait for this promise before to call you back. If you need to download locally an internet resource, the Scheduler does not need to call you before and you can set a promise to wait for the download to be done.
  • setWork : calling it providing a function tells the scheduler which function to call when it wants to continue your processing (after the execution of more importants tasks).
  • shouldYield : read this to know if the function should yield : if true, you set the next function to call using the setWork function and you returns. If false, you do your job.

So how do we implement this feature ? By creating a processing function which will process each part in a loop. At each cycle, we will check if we have to yield. If so, we tells the scheduler to call us back when it wants to restart our process. If the process is done (10 parts processed) then we just returns.

Here is how I will implement this “10 parts processing”.

var partProcessed = 0;
function executeYieldingTask() {
    // schedule some work
    S.schedule(function myScheduledJob(jobInfo) {
        //Process the 10 parts
        while (partProcessed < 10) {
            //check if I have to yield :new job with higher priority
            // may have been scheduled
            if (jobInfo.shouldYield) {
                //tells the Scheduler to execute myScheduledJob
                // when it's done executing higher priority task 
                //we yield so we exit the 'process loop'
            else {
                /* process the part partProcessed */
                partProcessed = partProcessed + 1;
    }, S.Priority.idle);

The IOwnerToken interface and how to use it

IOwnerToken is an interface which represents the owner of a job. By owner it means “master” : the one who controls and manage it.
A token can be set to multiple jobs at once and there is one function on this interface : cancelAll. This function simply cancel all the jobs owned by the token.

To create a token, you have to call the createOwnerToken function. You can then assign it to created job.

//create a token
var ownerToken = WinJS.Utilities.Scheduler.createOwnerToken();
//create jobs
var job1 =  WinJS.Utilities.Scheduler.schedule( /* ...*/);
var job2 =  WinJS.Utilities.Scheduler.schedule( /* ...*/);
//Be in control
job1.owner = ownerToken ;
job2.owner = ownerToken ;
//Cancel the jobs at once :

This token is then really useful when you want to manage a group of jobs at once. Create an owner, if the user do something else, goes to another page : you cancel all the task at once and retrieve some CPU juice.

Some useful functions

Now let’s discover some useful functions when playing with jobs and the scheduler.

  • requestDrain : use this function if you want to be sure that all scheduled jobs at a given priority are over. Simply pass the targeted priority, it returns a promise which can be use to know the completion of the “error state” of the queue processing
  • retrieveState : you need to dump the schedule queue for debug purpose ? Use this function :) . It dumps the name, the id, the priority of the tasks, etc.
  • schedulePromiseXXX : there is a lot of functions with similar names(schedulePromiseAboveNormal, etc.). These functions takes a promise as a parameter. It assures that the completion/error handler is processed on the scheduler with the given priority. If you want a completion handler tob be processed as soon as the promise is done, then use schedulePromiseHigh.

Here are some code example :

//requestDrain example
var drainPromise = WinJS.Utilities.Scheduler.requestDrain(priority, name);
      function complete(){console.log("queue drained");},
      function error(){ });
//retrieveState example :  
var S= WinJS.Utilities.Scheduler;
S.schedule(function () {/* */ }, S.Priority.aboveNormal,null,"a task name");
S.schedule(function () {/* */ }, S.Priority.idle,null, "infinite square name");
S.schedule(function () {/* */ }, S.Priority.belowNormal,null,"another task name");
var state = WinJS.Utilities.Scheduler.retrieveState();
  state looks like this :
     id: 22, priority: aboveNormal, name: a task name
     id: 24, priority: belowNormal, name: another task name
     id: 23, priority: idle, name: infinite square name
    Drain requests:
//schedulePromiseXXX example
var dldPromise = WinJS.xhr({url:'www.infiniteSquare.com'});
     /* process interesting content */

The Mobile Zone is brought to you in partnership with Strongloop and IBM.  Visually compose APIs with easy-to-use tooling. Learn how IBM API Connect provides near-universal access to data and services both on-premises and in the cloud.


Published at DZone with permission of Jon Antoine, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}