Scheduling a non-essential work in AngularJS Using requestIdleCallback

September 23, 2016

no comments

Hi guys,

As you all know, the browser runs on a single thread, meaning it can only do one thing at a time. so for example, every JavaScript function, handling a mouse click or just rendering an HTML, will be processed ONE by ONE, thus, some operations and processes would need to stop working while the first is still processed.

Things become more complicated when we encounter a script because, first the browser needs to download the script (if necessary) and only then will it run it. As you might have already guessed, everything else STOPS and causes the browser to become unresponsive resulting a poor user experience.

 

What happens when we need to perform some kind of background tasks like sending analytics data while the user is still scrolling the page or pre-fetching content while the user happens to be tapping on the button?

 

One option is to use Web Workers which can run code concurrently in a separate thread, but, it also has a down-side – you’re not permitted to directly access or update the DOM.

Hello requestIdleCallback

 

requestIdleCallback is a new API designed to schedule non-essential background tasks when there is either free time at the end of a frame, or when the user is inactive.
This means that there’s an opportunity to do your work without getting in the user’s way.

Since this new API is available only on Chrome 47 and above, we should check first that it’s available for use:

if ('requestIdleCallback' in window) {
  // Use requestIdleCallback to schedule work.
 } else {
  // no support - do something else
 setTimeout(backgroundTask1, 1);
 setTimeout(backgroundTask2, 1);
 setTimeout(backgroundTask3, 1);
 
 }
  • You can also shim its behavior.

Using requestIdleCallback

 

Callback:

A reference to a function that will be called during a browser’s idle period. The callback function must take the following parameters:

  • timeRemaining: A reference to a method that returns a DOMHighResTimeStamp.
  • didTimeout: A boolean that returns true if the callback was invoked by the user agent, and false otherwise.

Options:

Contains optional configuration parameters. It has the following property:

  • timeout: A deadline by which the browser must call the given callback function. This value is given in milliseconds.
requestIdleCallback(myNonEssentialWork);
 function myNonEssentialWork (deadline) {
   while (deadline.timeRemaining() > 0)
     doWorkIfNeeded();
 }

Guaranteeing your function is called:

requestIdleCallback(processPendingAnalyticsEvents, { timeout: 2000 });

• Guaranteeing your function is called within the first two seconds.

Angular Say Hello to requestIdleCallback

 

Since we are using requestIdleCallback API that invokes our function tasks, Angular has no clue that something has changed, so the trick here is to remember to call the $apply() function, so Angular could digest and make the appropriate changes.

 

I have created an Angular service you could use as a starting point for your non-essential background tasks.

app.factory("backgroundTask",function($window,$timeout,$rootScope){
 var tasks;
 
function addBackgroundTasks(taskList){
 tasks=angular.isArray(taskList)?taskList:[];
 
 if ('requestIdleCallback' in $window) {
 // requestIdleCallback supported
 requestIdleCallback(backgroundTask);
}
else {
 // no support
 while (tasks.length) {
 $timeout(task.shift(), 1);
 }
}
}


function backgroundTask (deadline) {
 // run next task if possible
 while (deadline.timeRemaining() > 0 && tasks.length > 0) {
 var task=tasks.shift();
 task();
 $rootScope.$apply();
 
 }

 // schedule further tasks if necessary
 if (tasks.length > 0) {
 requestIdleCallback(backgroundTask);
 }
}

return{
 add:addBackgroundTasks
}

});

Live example:
https://plnkr.co/edit/IQbYTj5DW7sSgGpNELPe?p=preview

 

Resources

How to Schedule Background Tasks in JavaScript by Craig Buckler

Using requestIdleCallback by Paul Lewis

https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback

 

Hope you’ll find this post helpful.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*