-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathwebWorkerLink.js
More file actions
97 lines (88 loc) · 2.68 KB
/
webWorkerLink.js
File metadata and controls
97 lines (88 loc) · 2.68 KB
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
import { DocumentNode, getOperationAST, parse } from 'graphql';
import { ApolloLink, Observable } from 'apollo-link';
import {
SubscriptionClient,
} from 'subscriptions-transport-ws';
import PromiseWorker from 'promise-worker';
import * as MessageTypes from './MessageTypes';
export class PromiseWorkerLink extends ApolloLink {
promiseWorker = null;
constructor({ worker }) {
super();
this.promiseWorker = new PromiseWorker(worker);
}
request(operation) {
return new Observable(observer => {
this.promiseWorker.postMessage(operation)
.then(data => {
observer.next(data);
observer.complete();
})
.catch(observer.error.bind(observer));
});
}
}
export const createWorkerInterface = ({ worker }) => {
class WorkerInterface {
url;
protocol;
readyState;
constructor(url, protocol) {
this.url = url;
this.protocol = protocol;
this.readyState = WorkerInterface.OPEN; // webworker is always opened
}
close() {
console.log('closing noop');
}
send(serializedMessage) {
worker.postMessage(serializedMessage);
}
set onerror(fn) {
worker.onerror = fn;
}
set onmessage(fn) {
worker.onmessage = ({ data }) => {
const d = (typeof data === "object") ? data : JSON.parse(data) ;
if (Object.keys(MessageTypes).map(k => MessageTypes[k]).indexOf(d.type) !== -1) {
fn({ data });
}
};
}
}
WorkerInterface.CLOSED = 'CLOSED';
WorkerInterface.OPEN = 'OPEN';
WorkerInterface.CONNECTING = 'CONNECTING';
return WorkerInterface;
}
export class SubscriptionWorkerLink extends ApolloLink {
worker = null;
subscriptionClient = null;
constructor({ worker }) {
super();
this.worker = worker;
this.subscriptionClient = new SubscriptionClient(null, {}, createWorkerInterface({ worker }));
}
request(operation) {
return this.subscriptionClient.request(operation);
}
}
export const isASubscriptionOperation = (document, operationName) => {
const operationAST = getOperationAST(document, operationName);
return !!operationAST && operationAST.operation === 'subscription';
};
export const createWebWorkerLink = ({ worker }) => {
const subscriptionWorkerLink = new SubscriptionWorkerLink({ worker });
const promiseWorkerLink = new PromiseWorkerLink({ worker });
const link = ApolloLink.split(
operation => {
const document = parse(operation.query);
return isASubscriptionOperation(document, operation.operationName);
},
subscriptionWorkerLink,
promiseWorkerLink
);
link.__subscriptionWorkerLink = subscriptionWorkerLink;
link.__promiseWorkerLink = promiseWorkerLink;
return link;
};