Last active
April 28, 2017 14:40
-
-
Save malcolmocean/567380c149129a93541ffc015c6e63ac to your computer and use it in GitHub Desktop.
Angular Worker-based Interval (to avoid Chrome background tab throttling)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var timers = {} | |
function fireInterval(id) { | |
this.postMessage({id: id}) | |
} | |
var commands = { | |
setInterval: function W_setInterval(data) { | |
var time = parseInt(data.time || 0, 10) | |
timer = setInterval(fireInterval.bind(null, data.id), time) | |
timers[data.id] = timer | |
}, | |
clearInterval: function W_clearInterval(data) { | |
if (timers[data.id]) { | |
clearInterval(timers[data.id]) | |
delete timers[data.id] | |
} | |
} | |
} | |
this.addEventListener('message', function(event) { | |
var data = event.data | |
if (commands[data.command]) { | |
commands[data.command](data) | |
} | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// $interval + Web Worker | |
// to avoid background timer throttling by Chrome (and maybe other browsers) | |
// heavily adapted from https://gist.github.com/BinaryMuse/19aa812cd2277d8c9555 | |
// returns an object that mostly behaves like $interval | |
// EXCEPT it just returns an id, not a promise | |
// (there may be other differences, but most of them would be downstream of this one) | |
// | |
// in browsers that don't support Worker, it just returns the $interval module | |
// either way, whatever it returns is still the thing to pass to .cancel() | |
app.provider('winterval', function WintervalProvider() { | |
function isDefined(value) {return typeof value !== 'undefined'} | |
this.$get = ['$rootScope', '$interval', | |
function($rootScope, $interval) { | |
if (typeof(Worker) == 'undefined') { | |
return $interval | |
} | |
var timers = {} | |
var intervalId = 0 | |
var worker = new Worker('/interval-worker.js') | |
worker.addEventListener('message', function (event) { | |
var data = event.data | |
var id = data.id | |
var timer = timers[id] | |
if (timer) { | |
var count = timer.count | |
var fn = timer.fn | |
var args = timer.args | |
if (timer.count > 0 && timer.iteration >= timer.count) { | |
worker.postMessage({command: "clearInterval", id: id}) | |
delete timers[id] | |
} | |
if (!timer.skipApply) $rootScope.$apply() | |
fn.apply(null, args) | |
} else { | |
console.log("worker attempted to access nonexistent timer") | |
worker.postMessage({command: "clearInterval", id: id}) | |
} | |
}) | |
function winterval(fn, delay, count, invokeApply) { | |
intervalId += 1 | |
delay = delay || 0 | |
var id = intervalId | |
timers[id] = { | |
fn: fn, | |
iteration: 0, | |
count: isDefined(count) ? count : 0, | |
skipApply: (isDefined(invokeApply) && !invokeApply) | |
// args: args | |
} | |
worker.postMessage({command: "setInterval", id: id, time: delay, count: count}) | |
return id | |
} | |
winterval.cancel = function (id) { | |
if (timers[id]) { | |
worker.postMessage({command: "clearInterval", id: id}) | |
delete timers[id] | |
return true | |
} | |
return false | |
} | |
return winterval | |
}] | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment