-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy paththread.js
129 lines (113 loc) · 4.56 KB
/
thread.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
(function (window, Worker, Blob, URL) {
'use strict';
var WorkerFactory = function (job) {
var singleThreadWorker = function (jobFunc) {
/* Single Thread Worker to support fallback for unsupported browsers */
var SingleWorker = function () {
this.result = null;
this.error = null;
this.postMessage = function (data) {
try {
this.result = jobFunc(data);
} catch (e) {
this.error = e;
}
};
this.close = function () {
this.result = null;
this.error = null;
};
};
return new SingleWorker(job);
}, multiThreadWorker = function (jobFunc) {
/* Multi Thread Worker that uses 'Worker' object */
var createBlob = function (response) {
var blob, BlobBuilder;
try {
blob = new Blob([response], { type: 'text/javascript' });
} catch (e) { /* Backwards-compatibility */
BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
blob = new BlobBuilder();
blob.append(response);
blob = blob.getBlob();
}
return blob;
},
jobCode = 'onmessage = function (msg) { var job = ' + jobFunc.toString() + '; var result = job(msg.data); this.postMessage(result); };',
blob = createBlob(jobCode),
url = URL.createObjectURL(blob),
workerInstance = new Worker(url);
workerInstance.close = function () {
this.terminate();
if (blob && url) { /* Release the blob URL when closing Worker */
URL.revokeObjectURL(url);
}
};
return workerInstance;
}, create = function (parallel) {
var workerInstance;
try {
workerInstance = (parallel === false) || !Worker ? singleThreadWorker(job) : multiThreadWorker(job);
} catch (e) { /* If Worker is not supported by the browser or causes issues, fallback to 'Single Thread Worker' mode */
workerInstance = singleThreadWorker(job);
}
return workerInstance;
};
return { create: create };
}, Thread = function (opt) {
var self = this, options = opt || {}, workerInstance, thenPromise, failPromise;
this.then = function (callback) {
if (workerInstance.result) { /* Initialize then promise */
callback.bind(this)(workerInstance.result);
}
thenPromise = callback;
return this;
};
this.fail = function (callback) {
if (workerInstance.error) { /* Initialize fail promise */
callback.bind(this)(workerInstance.error);
}
failPromise = callback;
return this;
};
this.start = function (data, job) {
/* Initialize worker instance */
workerInstance = WorkerFactory(job).create(options.parallel);
workerInstance.onmessage = function (msg) {
/* After executing the job, call 'then' promise */
if (typeof thenPromise === 'function') {
thenPromise.bind(self)(msg.data);
}
};
workerInstance.onerror = function (msg) {
/* If error occurs while executing code call 'fail' promise */
if (typeof failPromise === 'function') {
failPromise.bind(self)(msg);
}
};
/* Start worker */
workerInstance.postMessage(data);
return this;
};
this.close = function () {
workerInstance.close();
};
this.reStart = function (data) {
/* Re-execute job with new parameters */
if (workerInstance.result) {
workerInstance.result = null;
}
if (workerInstance.error) {
workerInstance.error = null;
}
workerInstance.postMessage(data);
return this;
};
this.id = options.id;
};
if (!window.Thread) {
/* Initialize global Thread object */
window.Thread = Thread;
}
return Thread;
}(window, window.Worker, Blob, window.URL || window.webkitURL));