Created
March 14, 2019 15:21
-
-
Save ayatty/06fd745c115723a8e0f8f2e639477fe9 to your computer and use it in GitHub Desktop.
Thread like context for Node.js (using async_hooks)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const asyncHooks = require('async_hooks'); | |
const asyncMap = {} | |
asyncHooks.createHook({ | |
init(asyncId, type, triggerAsyncId) { | |
const parent = asyncHooks.executionAsyncId(); | |
// 親がスレッドに属していれば子も属す | |
if (asyncMap[parent]) { | |
asyncMap[asyncId] = asyncMap[parent]; | |
// そうでなければメインスレッドに所属 | |
} else { | |
asyncMap[asyncId] = mainThread; | |
} | |
}, | |
destroy(asyncId) { | |
delete(asyncMap[asyncId]); | |
}, | |
promiseResolve(asyncId) { | |
delete(asyncMap[asyncId]); | |
}, | |
}).enable(); | |
class Thread { | |
constructor(entryFunction, threadLabel) { | |
this.entryFunction = entryFunction; | |
this.label = threadLabel; | |
} | |
run() { | |
const self = this; | |
const args = arguments; | |
return new Promise((resolve, reject) => { | |
setImmediate(() => { | |
asyncMap[asyncHooks.executionAsyncId()] = self; | |
try { | |
resolve(self.entryFunction(...args)); | |
} catch (e) { | |
reject(e); | |
} | |
}); | |
}); | |
} | |
} | |
const mainThread = new Thread(null, 'MainThread'); | |
function getCurrentThread() { | |
const eid = asyncHooks.executionAsyncId(); | |
if (asyncMap[eid]) { | |
return asyncMap[eid]; | |
} | |
return mainThread; | |
} | |
// | |
// ここからは動作確認用のコード | |
// | |
function printAsyncId(label) { | |
const cThread = getCurrentThread(); | |
process._rawDebug(`(${cThread.label})${label}: eid=${asyncHooks.executionAsyncId()} tid=${asyncHooks.triggerAsyncId()}`); | |
} | |
function delayPrint(delay) { | |
printAsyncId('delayPrint start'); | |
return new Promise((resolve, reject) => { | |
setTimeout(() => { | |
printAsyncId('delayPrint on timeout'); | |
console.log(getCurrentThread().text); | |
printAsyncId('delayPrint before resolve'); | |
resolve(); | |
//reject(); | |
}, delay); | |
}); | |
} | |
async function asyncFunction(text, delay) { | |
printAsyncId('run start'); | |
getCurrentThread().text = text; | |
await delayPrint(delay); | |
printAsyncId('run end'); | |
} | |
printAsyncId('Main-Start'); | |
const threadA = (new Thread(asyncFunction, 'aaa-delayPrint')).run('aaaaa', 1500); | |
printAsyncId('Main-Middle1'); | |
const threadB = (new Thread(asyncFunction, 'bbb-delayPrint')).run('bbbbb', 1000); | |
const threadC = (new Thread(console.log, 'console.log')).run('ccccc'); | |
printAsyncId('Main-End'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment