1 | import v4 from 'uuid-v4'
|
2 |
|
3 | export class Unpack {
|
4 | constructor() {
|
5 | this.id = v4()
|
6 | this.worker = new Worker(window.URL.createObjectURL(new Blob([require('../dist/bundle.js')])))
|
7 | this.promises = {}
|
8 | this.requests = 0
|
9 |
|
10 | this.worker.addEventListener(
|
11 | 'message',
|
12 | message => {
|
13 | switch (message.data.action) {
|
14 | case 'Finished':
|
15 | var resolve = this.promises[message.data.task].resolve
|
16 | delete this.promises[message.data.task]
|
17 | resolve(message.data)
|
18 |
|
19 | if (--this.requests < 0) this.requests = 0
|
20 | break
|
21 |
|
22 | case 'Result':
|
23 | if (!!this.promises[message.data.task].callback) {
|
24 | this.promises[message.data.task].callback(message.data.result)
|
25 | }
|
26 | break
|
27 | }
|
28 | },
|
29 | false,
|
30 | )
|
31 | }
|
32 |
|
33 |
|
34 | post(obj, callback) {
|
35 | obj.parent = this.id
|
36 | obj.task = v4()
|
37 | let task = { callback: callback }
|
38 | this.promises[obj.task] = task
|
39 | task.promise = new Promise(resolve => {
|
40 | task.resolve = resolve
|
41 | if (obj.type === 'Binary') {
|
42 | this.worker.postMessage(obj, [obj.data.buffer])
|
43 | } else {
|
44 | this.worker.postMessage(JSON.stringify(obj))
|
45 | }
|
46 | })
|
47 | return task.promise
|
48 | }
|
49 |
|
50 |
|
51 | static getFreeCore() {
|
52 | let core = undefined
|
53 | for (let candidate of cores) {
|
54 | if (candidate.requests == 0 && Object.keys(candidate.promises).length == 0) {
|
55 | core = candidate
|
56 | break
|
57 | }
|
58 | }
|
59 |
|
60 | if (core === undefined) {
|
61 | const sorted = cores.sort((a, b) => a.requests > b.requests)
|
62 | const candidates = sorted.filter(c => c.requests === sorted[0].requests)
|
63 | core = candidates[Math.round(Math.random() * (candidates.length - 1))]
|
64 | }
|
65 |
|
66 | core.requests++
|
67 | return core
|
68 | }
|
69 |
|
70 | static callWorkers(props) {
|
71 | for (let core of cores) {
|
72 | core.worker.postMessage(props)
|
73 | }
|
74 | }
|
75 | }
|
76 |
|
77 |
|
78 | let cores = Array.from(new Array(navigator.hardwareConcurrency || 4), () => new Unpack())
|
79 |
|
80 |
|
81 | export default function unpack(object, callback) {
|
82 | return Unpack.getFreeCore().post(object, callback)
|
83 | }
|