@@ -57,7 +57,7 @@ function createProtocol<P extends Protocol>(script: string) {
57
57
new Promise < P [ K ] [ 'out' ] > ( ( resolve , reject ) => {
58
58
let worker = new Worker ( script )
59
59
worker . onerror = reject
60
- worker . onmessage = event => resolve ( event . data . data )
60
+ worker . onmessage = event => resolve ( event . data )
61
61
worker . postMessage ( { command, args} )
62
62
} )
63
63
}
@@ -73,32 +73,57 @@ parallelDeterminant([[1, 2], [3, 4]]).then(
73
73
74
74
// WorkerScript.ts
75
75
76
- let handlers : {
77
- [ C in keyof MatrixProtocol ] : (
78
- ...args : MatrixProtocol [ C ] [ 'in' ]
79
- ) => MatrixProtocol [ C ] [ 'out' ]
80
- } = {
81
- determinant ( matrix ) {
82
- return determinant ( matrix )
83
- } ,
84
- [ 'dot-product' ] ( a , b ) {
85
- return dotProduct ( a , b )
86
- } ,
87
- invert ( matrix ) {
88
- return invert ( matrix )
76
+ type Data <
77
+ P extends Protocol ,
78
+ C extends keyof P = keyof P
79
+ > = C extends C
80
+ ? { command : C ; args : P [ C ] [ 'in' ] }
81
+ : never
82
+
83
+ function handle ( data : Data < MatrixProtocol > ) : MatrixProtocol [ typeof data . command ] [ 'out' ] {
84
+ switch ( data . command ) {
85
+ case 'determinant' :
86
+ return determinant ( ...data . args )
87
+ case 'dot-product' :
88
+ return dotProduct ( ...data . args )
89
+ case 'invert' :
90
+ return invert ( ...data . args )
89
91
}
90
92
}
91
93
92
- onmessage = < C extends keyof MatrixProtocol > ( {
93
- data : { command, args}
94
- } : {
95
- data : { command : C ; args : MatrixProtocol [ C ] [ 'in' ] }
96
- } ) => {
97
- let handler = handlers [ command ]
98
- let result = handler ( ...args )
99
- postMessage ( result )
100
- }
94
+ onmessage = ( { data} ) => postMessage ( handle ( data ) )
101
95
102
96
declare function determinant ( matrix : Matrix ) : number
103
97
declare function dotProduct ( matrixA : Matrix , matrixB : Matrix ) : Matrix
104
98
declare function invert ( matrix : Matrix ) : Matrix
99
+
100
+ // 3. Use a mapped type (as in 「8.6.1 In the Browser: With Web Workers★」) to implement a typesafe message-passing protocol for NodeJS's `child_process`.
101
+
102
+ // MainThread.ts
103
+ import { fork } from 'child_process'
104
+
105
+ function createProtocolCP < P extends Protocol > ( script : string ) {
106
+ return < K extends keyof P > ( command : K ) => ( ...args : P [ K ] [ 'in' ] ) =>
107
+ new Promise < P [ K ] [ 'out' ] > ( ( resolve , reject ) => {
108
+ let child = fork ( script )
109
+ child . on ( 'error' , reject )
110
+ child . on ( 'message' , resolve )
111
+ child . send ( { command, args} )
112
+ } )
113
+ }
114
+
115
+ let runWithMatrixProtocolCP = createProtocolCP < MatrixProtocol > (
116
+ './ChildThread.js'
117
+ )
118
+ let parallelDeterminantCP = runWithMatrixProtocolCP ( 'determinant' )
119
+
120
+ parallelDeterminantCP ( [ [ 1 , 2 ] , [ 3 , 4 ] ] ) . then (
121
+ determinant => console . log ( determinant ) // -2
122
+ )
123
+
124
+ // ChildThread.ts
125
+
126
+ // type Data ...
127
+ // function handle ...
128
+
129
+ process . on ( 'message' , data => process . send ! ( handle ( data ) ) )
0 commit comments