Skip to content

Commit d947eb2

Browse files
author
fresa
committed
made a few changes in preparation of registering in bower
1 parent 936bb13 commit d947eb2

File tree

6 files changed

+243
-19
lines changed

6 files changed

+243
-19
lines changed

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ root = true
22

33
[*]
44
indent_style = space
5-
indent_size = 2
5+
indent_size = 4
66
end_of_line = lf
77
charset = utf-8
88
trim_trailing_whitespace = true

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,3 @@
22
node_modules
33
components
44
bower_components
5-
dist

Gruntfile.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ module.exports = function (grunt) {
3737
concat: {
3838
src: {
3939
src: ['src/**/*.js'],
40-
dest: 'dist/angular-component-<%= pkg.version %>.js'
40+
dest: 'dist/angular-workers-<%= pkg.version %>.js'
4141
}
4242
},
4343
uglify: {
4444
src: {
4545
files: {
46-
'dist/angular-component-<%= pkg.version %>.min.js': '<%= concat.src.dest %>'
46+
'dist/angular-workers-<%= pkg.version %>.min.js': '<%= concat.src.dest %>'
4747
}
4848
}
4949
},

bower.json

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,30 @@
11
{
2-
"author": "Fredrik Sandell",
3-
"name": "angular-workers",
4-
"description": "Web workers wrapper for angular",
5-
"version": "0.1.1",
6-
"homepage": "http://github.com/FredrikSandell/angular-workers",
7-
"repository": {
8-
"type": "git",
9-
"url": "git://github.com/FredrikSandell/angular-workers"
10-
},
11-
"dependencies": {
12-
"angular": "~1.3.11"
13-
},
14-
"devDependencies": {
15-
"angular-mocks": "~1.3.11"
16-
}
2+
"author": "Fredrik Sandell",
3+
"name": "angular-workers",
4+
"description": "Web workers wrapper for angular",
5+
"version": "1.0.0",
6+
"homepage": "http://github.com/FredrikSandell/angular-workers",
7+
"repository": {
8+
"type": "git",
9+
"url": "git://github.com/FredrikSandell/angular-workers"
10+
},
11+
"ignore": [
12+
'src',
13+
'test',
14+
'.bowerrc',
15+
'.gitignore',
16+
'.jshintrc',
17+
'.travis.yml',
18+
'.editorconfig',
19+
'bower.json',
20+
'Gruntfile.js',
21+
'package.json',
22+
'karma.conf.js'
23+
],
24+
"dependencies": {
25+
"angular": "~1.3.*"
26+
},
27+
"devDependencies": {
28+
"angular-mocks": "~1.3.*"
29+
}
1730
}

dist/angular-workers-1.0.0.js

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
angular.module('FredrikSandell.worker-pool-pi-calculator', []).service('PiCalculatorService', [
2+
'$q',
3+
function ($q) {
4+
var that = {};
5+
/**
6+
* If this is done correctly really doesn't matter. What we need is a long running task which hogs CPU-time.
7+
* Number of decimals to calculate for PI
8+
* @param num
9+
*/
10+
that.calculatePi = function (num) {
11+
var deferred = $q.defer();
12+
var pi = 4, top = 4, bot = 3, minus = true;
13+
var startTime = Date.now();
14+
var somewhatExactPi = next(pi, top, bot, minus, num, deferred);
15+
deferred.resolve({
16+
pi: somewhatExactPi,
17+
runtime: calculateRuntime(startTime, Date.now())
18+
});
19+
return deferred.promise;
20+
};
21+
function next(pi, top, bot, minus, num, deferred) {
22+
for (var i = 0; i < num; i++) {
23+
pi += minus ? -(top / bot) : top / bot;
24+
minus = !minus;
25+
bot += 2;
26+
if (i % 1000 === 0) {
27+
deferred.notify(pi);
28+
}
29+
}
30+
return pi;
31+
}
32+
function calculateRuntime(start, end) {
33+
var total = end - start;
34+
if (total >= 1000) {
35+
total = total / 1000 + 'seconds';
36+
} else {
37+
total += 'ms';
38+
}
39+
return total;
40+
}
41+
return that;
42+
}
43+
]);
44+
angular.module('FredrikSandell.worker-pool', []).service('WorkerService', [
45+
'$q',
46+
function ($q) {
47+
var that = {};
48+
//this should be configured from the app in the future
49+
var urlToAngular = 'http://localhost:9876/base/bower_components/angular/angular.js';
50+
var serviceToUrlMap = {};
51+
that.setAngularUrl = function (urlToAngularJs) {
52+
urlToAngular = urlToAngularJs;
53+
};
54+
function createAngularWorkerTemplate() {
55+
/*jshint laxcomma:true */
56+
/*jshint quotmark: false */
57+
var workerTemplate = [
58+
'',
59+
'//try {',
60+
'var window = self;',
61+
'self.history = {};',
62+
'var document = {',
63+
' readyState: \'complete\',',
64+
' cookie: \'\',',
65+
' querySelector: function () {},',
66+
' createElement: function () {',
67+
' return {',
68+
' pathname: \'\',',
69+
' setAttribute: function () {}',
70+
' };',
71+
' }',
72+
'};',
73+
'importScripts(\'<URL_TO_ANGULAR>\');',
74+
'<CUSTOM_DEP_INCLUDES>',
75+
'angular = window.angular;',
76+
'var workerApp = angular.module(\'WorkerApp\', [<DEP_MODULES>]);',
77+
'workerApp.run([\'$q\'<STRING_DEP_NAMES>, function ($q<DEP_NAMES>) {',
78+
' self.addEventListener(\'message\', function(e) {',
79+
' var input = e.data;',
80+
' var output = $q.defer();',
81+
' var promise = output.promise;',
82+
' promise.then(function(success) {',
83+
' self.postMessage({event:\'success\', data : success});',
84+
' }, function(reason) {',
85+
' self.postMessage({event:\'failure\', data : reason});',
86+
' }, function(update) {',
87+
' self.postMessage({event:\'update\', data : update});',
88+
' });',
89+
' <WORKER_FUNCTION>;',
90+
' });',
91+
' self.postMessage({event:\'initDone\'});',
92+
'}]);',
93+
'angular.bootstrap(null, [\'WorkerApp\']);',
94+
'//} catch(e) {self.postMessage(JSON.stringify(e));}'
95+
];
96+
return workerTemplate.join('\n');
97+
}
98+
var workerTemplate = createAngularWorkerTemplate();
99+
that.addDependency = function (serviceName, moduleName, url) {
100+
serviceToUrlMap[serviceName] = {
101+
url: url,
102+
moduleName: moduleName
103+
};
104+
return that;
105+
};
106+
function createIncludeStatements(listOfServiceNames) {
107+
var includeString = '';
108+
angular.forEach(listOfServiceNames, function (serviceName) {
109+
if (serviceToUrlMap[serviceName]) {
110+
includeString += 'importScripts(\'' + serviceToUrlMap[serviceName].url + '\');';
111+
}
112+
});
113+
return includeString;
114+
}
115+
function createModuleList(listOfServiceNames) {
116+
var moduleNameList = [];
117+
angular.forEach(listOfServiceNames, function (serviceName) {
118+
if (serviceToUrlMap[serviceName]) {
119+
moduleNameList.push('\'' + serviceToUrlMap[serviceName].moduleName + '\'');
120+
}
121+
});
122+
return moduleNameList.join(',');
123+
}
124+
function createDependencyMetaData(dependencyList) {
125+
var dependencyServiceNames = dependencyList.filter(function (dep) {
126+
return dep !== 'input' && dep !== 'output' && dep !== '$q';
127+
});
128+
var depMetaData = {
129+
dependencies: dependencyServiceNames,
130+
moduleList: createModuleList(dependencyServiceNames),
131+
angularDepsAsStrings: dependencyServiceNames.length > 0 ? ',' + dependencyServiceNames.map(function (dep) {
132+
return '\'' + dep + '\'';
133+
}).join(',') : '',
134+
angularDepsAsParamList: dependencyServiceNames.length > 0 ? ',' + dependencyServiceNames.join(',') : '',
135+
servicesIncludeStatements: createIncludeStatements(dependencyServiceNames)
136+
};
137+
depMetaData.workerFuncParamList = 'input,output' + depMetaData.angularDepsAsParamList;
138+
return depMetaData;
139+
}
140+
function populateWorkerTemplate(workerFunc, dependencyMetaData) {
141+
return workerTemplate.replace('<URL_TO_ANGULAR>', urlToAngular).replace('<CUSTOM_DEP_INCLUDES>', dependencyMetaData.servicesIncludeStatements).replace('<DEP_MODULES>', dependencyMetaData.moduleList).replace('<STRING_DEP_NAMES>', dependencyMetaData.angularDepsAsStrings).replace('<DEP_NAMES>', dependencyMetaData.angularDepsAsParamList).replace('<WORKER_FUNCTION>', workerFunc.toString());
142+
}
143+
var buildAngularWorker = function (initializedWorker) {
144+
var that = {};
145+
that.worker = initializedWorker;
146+
that.run = function (input) {
147+
var deferred = $q.defer();
148+
initializedWorker.addEventListener('message', function (e) {
149+
var eventId = e.data.event;
150+
//console.log(e.data);
151+
if (eventId === 'initDone') {
152+
throw 'Received worker initialization in run method. This should already have occurred!';
153+
} else if (eventId === 'success') {
154+
deferred.resolve(e.data.data);
155+
} else if (eventId === 'failure') {
156+
deferred.reject(e.data.data);
157+
} else if (eventId === 'update') {
158+
deferred.notify(e.data.data);
159+
} else {
160+
deferred.reject(e);
161+
}
162+
});
163+
initializedWorker.postMessage(input);
164+
return deferred.promise;
165+
};
166+
that.terminate = function () {
167+
initializedWorker.terminate();
168+
};
169+
return that;
170+
};
171+
var extractDependencyList = function (depFuncList) {
172+
return depFuncList.slice(0, depFuncList.length - 1);
173+
};
174+
var workerFunctionToString = function (func, paramList) {
175+
return '(' + func.toString() + ')(' + paramList + ')';
176+
};
177+
/**
178+
* example call:
179+
* WorkerService.createAngularWorker(['input', 'output', '$http', function(input, output, $http)
180+
* {body of function}]);
181+
* Parameters "input" and "output" is required. Not defining them will cause a runtime error.
182+
* Declaring services to be injected, as '$http' is above, requires the web worker to be able to resolve them.
183+
* '$http' service is a part of the standard angular package which means it will resolve without additional information
184+
* since angular source is always loaded in the web worker.
185+
* But if a custom service was to be injected the WorkerService would need be be informed on how to resolve the.
186+
* @param depFuncList
187+
*/
188+
that.createAngularWorker = function (depFuncList) {
189+
//validate the input
190+
if (!Array.isArray(depFuncList) || depFuncList.length < 3 || typeof depFuncList[depFuncList.length - 1] !== 'function') {
191+
throw 'Input needs to be: [\'workerInput\',\'deferredOutput\'/*optional additional dependencies*/,\n' + ' function(workerInput, deferredOutput /*optional additional dependencies*/)\n' + ' {/*worker body*/}' + ']';
192+
}
193+
var deferred = $q.defer();
194+
var dependencyMetaData = createDependencyMetaData(extractDependencyList(depFuncList));
195+
var blobURL = (window.webkitURL ? webkitURL : URL).createObjectURL(new Blob([populateWorkerTemplate(workerFunctionToString(depFuncList[depFuncList.length - 1], dependencyMetaData.workerFuncParamList), dependencyMetaData)], { type: 'application/javascript' }));
196+
var worker = new Worker(blobURL);
197+
//wait for the worker to load resources
198+
worker.addEventListener('message', function (e) {
199+
var eventId = e.data.event;
200+
console.log(e.data);
201+
if (eventId === 'initDone') {
202+
deferred.resolve(buildAngularWorker(worker));
203+
} else {
204+
deferred.reject(e);
205+
}
206+
});
207+
return deferred.promise;
208+
};
209+
return that;
210+
}
211+
]);

dist/angular-workers-1.0.0.min.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)