@@ -57,7 +57,7 @@ function createProtocol<P extends Protocol>(script: string) {
5757 new Promise < P [ K ] [ 'out' ] > ( ( resolve , reject ) => {
5858 let worker = new Worker ( script )
5959 worker . onerror = reject
60- worker . onmessage = event => resolve ( event . data . data )
60+ worker . onmessage = event => resolve ( event . data )
6161 worker . postMessage ( { command, args} )
6262 } )
6363}
@@ -73,32 +73,57 @@ parallelDeterminant([[1, 2], [3, 4]]).then(
7373
7474// WorkerScript.ts
7575
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 )
8991 }
9092}
9193
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 ) )
10195
10296declare function determinant ( matrix : Matrix ) : number
10397declare function dotProduct ( matrixA : Matrix , matrixB : Matrix ) : Matrix
10498declare 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