Created
October 16, 2016 01:32
-
-
Save evillemez/ee9791a7cc4d8a343358d9dbb08cf659 to your computer and use it in GitHub Desktop.
This was an old hacky attempt at a promise-based API for running any function in a web worker. Never got around to fleshing it out.
This file contains 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
//Code for async web worker | |
var fibonacciWorkerTask = function(iterations) { | |
var first,second,add; | |
for (var i=0; i<iterations; i++) { | |
if (i === 0) { | |
first = 1; | |
second = 2; | |
} | |
if (first+second > Number.MAX_VALUE) { | |
throw new Error('Exceeded maximum value of ['+Number.MAX_VALUE+'].'); | |
} | |
add = first + second; | |
first = second; | |
second = add; | |
task.progress(i / iterations * 100); | |
} | |
task.progress(100); | |
task.finish(add); | |
}; | |
angular.module('job', []) | |
.controller('JobController', function($scope) { | |
//create a job | |
var fibonacci = WorkerTask.create(fibonacciWorkerTask); | |
$scope.result = null; | |
$scope.progress = null; | |
$scope.getStatus = function() { | |
return fibonacci.isRunning() ? 'running' : 'not running'; | |
}; | |
//run the job | |
fibonacci.run(2000) | |
.then(function(res) { | |
$scope.$apply(function() { | |
$scope.result = res; | |
}); | |
}) | |
.catch(function(err) { | |
$scope.$apply(function() { | |
$scope.result = 'ERROR: ' + err; | |
}); | |
throw new Error(err); | |
}) | |
.progress(function(percent) { | |
$scope.$apply(function() { | |
$scope.progress = percent; | |
}); | |
}) | |
.finally(function() { | |
console.log("Done working!"); | |
}) | |
.done(); | |
}); |
This file contains 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
<!doctype html> | |
<html> | |
<head> | |
<script src='bower_components/angularjs/angular.js'></script> | |
<script src='bower_components/q/q.js'></script> | |
<script src='worker-task.js'></script> | |
<script src='example.js'></script> | |
</head> | |
<body ng-app='job'> | |
<h1>An example job...</h1> | |
<div id='job' ng-controller='JobController'> | |
<p>The job is currently... {{getStatus()}}</p> | |
<p>Progress: {{progress}}%</p> | |
<p>And the result is: {{result}}</p> | |
</div> | |
</body> | |
</html> |
This file contains 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
(function() { | |
var workerTaskContent = (function() { | |
return function (e) { | |
var cmd = e.data.cmd; | |
var input = e.data.input; | |
this.task = { | |
finish: function(result) { postMessage({cmd: 'finish', data: result}); }, | |
progress: function(progress) { postMessage({cmd: 'progress', data: progress}); }, | |
error: function(error) { postMessage({cmd: 'error', data: error}); } | |
}; | |
//TODO: consider this.on(); for registering specific command handlers. | |
var __taskFunc = (function() { return /*INSERT*/ })(); | |
switch (cmd) { | |
case 'run': | |
try { | |
var result = __taskFunc(input); | |
if(result) { task.finish(result); } | |
} catch (e) { | |
task.error(e.message); | |
} | |
break; | |
} | |
}; | |
})().toString(); | |
function WorkerTask(taskFunc, timeout, autoTerminate) { | |
this._deferred = Q.defer(); | |
this._taskFunc = taskFunc; | |
this._timeout = (timeout === null) ? 0 : timeout; | |
this._autoTerminate = (autoTerminate === true) ? true : false; | |
this._running = false; | |
this._objUrl = null; | |
this._worker = null; | |
//convert worker logic to string, injecting the passed function as a string | |
var workerString = "onmessage = " + workerTaskContent.replace("/*INSERT*/", taskFunc.toString()); | |
//setup the worker | |
this._objUrl = window.URL.createObjectURL(new Blob([workerString])); | |
this._worker = new Worker(this._objUrl); | |
//setup handler for worker responses | |
var self = this; | |
this._worker.onmessage = function(e) { | |
var cmd = e.data.cmd; | |
var data = e.data.data; | |
switch (cmd) { | |
case 'finish': | |
self._running = false; | |
self._deferred.resolve(data); | |
if(self._autoTerminate) { | |
self._worker.terminate(); | |
window.URL.revokeObjectURL(self._objUrl); | |
} | |
break; | |
case 'progress': | |
self._deferred.notify(data); | |
break; | |
case 'error': | |
self._running = false; | |
self._deferred.reject(data); | |
if(self._autoTerminate) { | |
self._worker.terminate(); | |
window.URL.revokeObjectURL(self._objUrl); | |
} | |
break; | |
} | |
}; | |
} | |
WorkerTask.prototype = { | |
isRunning: function () { return this._running; }, | |
getWorker: function() { return this._worker; }, | |
terminate: function() { | |
this._worker.terminate(); | |
window.URL.revokeObjectURL(this._objUrl); | |
}, | |
run: function(input, transferables) { | |
this._running = true; | |
//TODO: implement transferable objects | |
this._worker.postMessage({cmd: 'run', input: input}); | |
//TODO: implement timeout tracking | |
return this._deferred.promise; | |
} | |
}; | |
WorkerTask.create = function(taskFunc) { | |
return new WorkerTask(taskFunc); | |
}; | |
//TODO: env check | |
this.WorkerTask = WorkerTask; | |
})(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment