Skip to content

Commit a09e395

Browse files
author
fresa
committed
cleaned up the code a bit
1 parent e7a24e6 commit a09e395

File tree

2 files changed

+116
-151
lines changed

2 files changed

+116
-151
lines changed

src/angular-workers.js

Lines changed: 93 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,56 @@
11
angular.module('FredrikSandell.worker-pool', [])
22
.service('WorkerService', ['$q', function ($q) {
33
var that = {};
4-
5-
//this should be configured from the app in the future
6-
var urlToAngular = 'http://localhost:9876/base/bower_components/angular/angular.js';
4+
var urlToAngular;
75
var serviceToUrlMap = {};
8-
9-
that.setAngularUrl = function(urlToAngularJs) {
6+
/*jshint laxcomma:true */
7+
/*jshint quotmark: false */
8+
var workerTemplate = [""
9+
// Angular needs a global window object \
10+
, "var window = self;"
11+
// Skeleton properties to get Angular to load and bootstrap. \
12+
, "self.history = {};"
13+
, "var document = {"
14+
, " readyState: 'complete',"
15+
, " cookie: '',"
16+
, " querySelector: function () {},"
17+
, " createElement: function () {"
18+
, " return {"
19+
, " pathname: '',"
20+
, " setAttribute: function () {}"
21+
, " };"
22+
, " }"
23+
, "};"
24+
// Load Angular: must be on same domain as this script \
25+
, "importScripts('<URL_TO_ANGULAR>');"
26+
, "<CUSTOM_DEP_INCLUDES>"
27+
// Put angular on global scope \
28+
, "angular = window.angular;"
29+
, "var workerApp = angular.module('WorkerApp', [<DEP_MODULES>]);"
30+
, "workerApp.run(['$q'<STRING_DEP_NAMES>, function ($q<DEP_NAMES>) {"
31+
, " self.addEventListener('message', function(e) {"
32+
, " var input = e.data;"
33+
, " var output = $q.defer();"
34+
, " var promise = output.promise;"
35+
, " promise.then(function(success) {"
36+
, " self.postMessage({event:'success', data : success});"
37+
, " }, function(reason) {"
38+
, " self.postMessage({event:'failure', data : reason});"
39+
, " }, function(update) {"
40+
, " self.postMessage({event:'update', data : update});"
41+
, " });"
42+
, " <WORKER_FUNCTION>;"
43+
, " });"
44+
, " self.postMessage({event:'initDone'});"
45+
, "}]);"
46+
, "angular.bootstrap(null, ['WorkerApp']);"].join("\n");
47+
48+
49+
that.setAngularUrl = function(urlToAngularJs) {
1050
urlToAngular = urlToAngularJs;
51+
return that;
1152
};
1253

13-
function createAngularWorkerTemplate() {
14-
/*jshint laxcomma:true */
15-
/*jshint quotmark: false */
16-
var workerTemplate = [""
17-
, "//try {"
18-
// Angular needs a global window object \
19-
, "var window = self;"
20-
// Skeleton properties to get Angular to load and bootstrap. \
21-
, "self.history = {};"
22-
, "var document = {"
23-
, " readyState: 'complete',"
24-
, " cookie: '',"
25-
, " querySelector: function () {},"
26-
, " createElement: function () {"
27-
, " return {"
28-
, " pathname: '',"
29-
, " setAttribute: function () {}"
30-
, " };"
31-
, " }"
32-
, "};"
33-
// Load Angular: must be on same domain as this script \
34-
, "importScripts('<URL_TO_ANGULAR>');"
35-
, "<CUSTOM_DEP_INCLUDES>"
36-
// Put angular on global scope \
37-
, "angular = window.angular;"
38-
, "var workerApp = angular.module('WorkerApp', [<DEP_MODULES>]);"
39-
, "workerApp.run(['$q'<STRING_DEP_NAMES>, function ($q<DEP_NAMES>) {"
40-
, " self.addEventListener('message', function(e) {"
41-
, " var input = e.data;"
42-
, " var output = $q.defer();"
43-
, " var promise = output.promise;"
44-
, " promise.then(function(success) {"
45-
, " self.postMessage({event:'success', data : success});"
46-
, " }, function(reason) {"
47-
, " self.postMessage({event:'failure', data : reason});"
48-
, " }, function(update) {"
49-
, " self.postMessage({event:'update', data : update});"
50-
, " });"
51-
, " <WORKER_FUNCTION>;"
52-
, " });"
53-
, " self.postMessage({event:'initDone'});"
54-
, "}]);"
55-
, "angular.bootstrap(null, ['WorkerApp']);"
56-
, "//} catch(e) {self.postMessage(JSON.stringify(e));}"];
57-
return workerTemplate.join("\n");
58-
}
59-
var workerTemplate = createAngularWorkerTemplate();
6054
that.addDependency = function (serviceName, moduleName, url) {
6155
serviceToUrlMap[serviceName] = {
6256
url : url,
@@ -65,6 +59,49 @@ angular.module('FredrikSandell.worker-pool', [])
6559
return that;
6660
};
6761

62+
that.createAngularWorker = function (depFuncList) {
63+
//validate the input
64+
65+
if (!Array.isArray(depFuncList) ||
66+
depFuncList.length < 3 ||
67+
typeof depFuncList[depFuncList.length - 1] !== 'function') {
68+
throw 'Input needs to be: [\'input\',\'output\'\/*optional additional dependencies*\/,\n' +
69+
' function(workerInput, deferredOutput \/*optional additional dependencies*\/)\n' +
70+
' {\/*worker body*\/}' +
71+
']';
72+
}
73+
if(typeof urlToAngular !== 'string') {
74+
throw 'The url to angular must be defined before worker creation';
75+
}
76+
var deferred = $q.defer();
77+
78+
var dependencyMetaData = createDependencyMetaData(extractDependencyList(depFuncList));
79+
80+
var blobURL = (window.webkitURL ? webkitURL : URL).createObjectURL(new Blob([
81+
populateWorkerTemplate(
82+
workerFunctionToString(
83+
depFuncList[depFuncList.length - 1],
84+
dependencyMetaData.workerFuncParamList),
85+
dependencyMetaData
86+
)], { type: 'application/javascript' }));
87+
88+
89+
var worker = new Worker(blobURL);
90+
91+
//wait for the worker to load resources
92+
worker.addEventListener('message', function (e) {
93+
var eventId = e.data.event;
94+
console.log(e.data);
95+
if (eventId === 'initDone') {
96+
deferred.resolve(buildAngularWorker(worker));
97+
} else {
98+
deferred.reject(e);
99+
}
100+
});
101+
102+
return deferred.promise;
103+
};
104+
68105
function createIncludeStatements(listOfServiceNames) {
69106
var includeString = '';
70107
angular.forEach(listOfServiceNames, function (serviceName) {
@@ -142,63 +179,13 @@ angular.module('FredrikSandell.worker-pool', [])
142179
return that;
143180
};
144181

145-
var extractDependencyList = function (depFuncList) {
182+
function extractDependencyList(depFuncList) {
146183
return depFuncList.slice(0, depFuncList.length - 1);
147-
};
184+
}
148185

149-
var workerFunctionToString = function (func, paramList) {
186+
function workerFunctionToString(func, paramList) {
150187
return '('+func.toString() + ')(' + paramList + ')';
151-
};
152-
/**
153-
* example call:
154-
* WorkerService.createAngularWorker(['input', 'output', '$http', function(input, output, $http)
155-
* {body of function}]);
156-
* Parameters "input" and "output" is required. Not defining them will cause a runtime error.
157-
* Declaring services to be injected, as '$http' is above, requires the web worker to be able to resolve them.
158-
* '$http' service is a part of the standard angular package which means it will resolve without additional information
159-
* since angular source is always loaded in the web worker.
160-
* But if a custom service was to be injected the WorkerService would need be be informed on how to resolve the.
161-
* @param depFuncList
162-
*/
163-
that.createAngularWorker = function (depFuncList) {
164-
//validate the input
165-
166-
if (!Array.isArray(depFuncList) ||
167-
depFuncList.length < 3 ||
168-
typeof depFuncList[depFuncList.length - 1] !== 'function') {
169-
throw 'Input needs to be: [\'workerInput\',\'deferredOutput\'\/*optional additional dependencies*\/,\n' +
170-
' function(workerInput, deferredOutput \/*optional additional dependencies*\/)\n' +
171-
' {\/*worker body*\/}' +
172-
']';
173-
}
174-
var deferred = $q.defer();
175-
176-
var dependencyMetaData = createDependencyMetaData(extractDependencyList(depFuncList));
177-
178-
var blobURL = (window.webkitURL ? webkitURL : URL).createObjectURL(new Blob([
179-
populateWorkerTemplate(
180-
workerFunctionToString(
181-
depFuncList[depFuncList.length - 1],
182-
dependencyMetaData.workerFuncParamList),
183-
dependencyMetaData
184-
)], { type: 'application/javascript' }));
185-
186-
187-
var worker = new Worker(blobURL);
188-
189-
//wait for the worker to load resources
190-
worker.addEventListener('message', function (e) {
191-
var eventId = e.data.event;
192-
console.log(e.data);
193-
if (eventId === 'initDone') {
194-
deferred.resolve(buildAngularWorker(worker));
195-
} else {
196-
deferred.reject(e);
197-
}
198-
});
199-
200-
return deferred.promise;
201-
};
188+
}
202189

203190
return that;
204191
}]);

test/unit/angular-workersSpec.js

Lines changed: 23 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ describe('FredrikSandell.worker-pool', function () {
1010
rootScope = $rootScope;
1111
});
1212
});
13+
beforeEach(function() {
14+
WorkerService.setAngularUrl('http://localhost:9876/base/bower_components/angular/angular.js');
15+
16+
});
1317

1418
it('should be an object', function () {
1519
expect(typeof WorkerService).toBe('object');
@@ -29,6 +33,18 @@ describe('FredrikSandell.worker-pool', function () {
2933
expect(WorkerService.setAngularUrl).toBeDefined();
3034
expect(typeof WorkerService.setAngularUrl).toBe('function');
3135
});
36+
37+
function waitUntilCompletedToTriggerPromiseResolve(completed, rootScope) {
38+
//must wait before triggering digest loop which resolves of the promises
39+
//worker must be given time to initialize
40+
var checker = setInterval(function(){
41+
if(completed) {
42+
clearInterval(checker);
43+
} else {
44+
rootScope.$apply();
45+
}
46+
}, 100);
47+
}
3248

3349
it('createAngularWorker() should return a valid AngularWorker object', function (done) {
3450
var completed = false;
@@ -46,16 +62,10 @@ describe('FredrikSandell.worker-pool', function () {
4662
done();
4763
completed = true;
4864
});
49-
//must wait before triggering digest loop which resolves of the promises
50-
//worker must be given time to initialize
51-
var checker = setInterval(function(){
52-
if(completed) {
53-
clearInterval(checker);
54-
} else {
55-
rootScope.$apply();
56-
}
57-
}, 100);
65+
waitUntilCompletedToTriggerPromiseResolve(completed, rootScope);
5866
});
67+
68+
5969

6070
it('should be possible to pass arguments to worker, send updates from workers, and successfully terminate workers', function (done) {
6171
var completed = false;
@@ -94,15 +104,7 @@ describe('FredrikSandell.worker-pool', function () {
94104
done();
95105
completed = true;
96106
});
97-
//must wait before triggering digest loop which resolves of the promises
98-
//worker must be given time to initialize
99-
var checker = setInterval(function(){
100-
if(completed) {
101-
clearInterval(checker);
102-
} else {
103-
rootScope.$apply();
104-
}
105-
}, 100);
107+
waitUntilCompletedToTriggerPromiseResolve(completed, rootScope);
106108
});
107109

108110
it('should be possible reject promise from worker', function (done) {
@@ -119,15 +121,7 @@ describe('FredrikSandell.worker-pool', function () {
119121
done();
120122
completed = true;
121123
});
122-
//must wait before triggering digest loop which resolves of the promises
123-
//worker must be given time to initialize
124-
var checker = setInterval(function(){
125-
if(completed) {
126-
clearInterval(checker);
127-
} else {
128-
rootScope.$apply();
129-
}
130-
}, 100);
124+
waitUntilCompletedToTriggerPromiseResolve(completed, rootScope);
131125
});
132126

133127
it('should be possible inject angular dependencies in worker', function (done) {
@@ -149,15 +143,7 @@ describe('FredrikSandell.worker-pool', function () {
149143
done();
150144
completed = true;
151145
});
152-
//must wait before triggering digest loop which resolves of the promises
153-
//worker must be given time to initialize
154-
var checker = setInterval(function(){
155-
if(completed) {
156-
clearInterval(checker);
157-
} else {
158-
rootScope.$apply();
159-
}
160-
}, 100);
146+
waitUntilCompletedToTriggerPromiseResolve(completed, rootScope);
161147
});
162148

163149
it('should be possible inject custom dependencies in worker', function (done) {
@@ -183,15 +169,7 @@ describe('FredrikSandell.worker-pool', function () {
183169
done();
184170
completed = true;
185171
});
186-
//must wait before triggering digest loop which resolves of the promises
187-
//worker must be given time to initialize
188-
var checker = setInterval(function(){
189-
if(completed) {
190-
clearInterval(checker);
191-
} else {
192-
rootScope.$apply();
193-
}
194-
}, 100);
172+
waitUntilCompletedToTriggerPromiseResolve(completed, rootScope);
195173
});
196174

197175
});

0 commit comments

Comments
 (0)