Last active
December 18, 2021 14:10
-
-
Save Yama-Tomo/75615688208d059cd9687ca1be5efb46 to your computer and use it in GitHub Desktop.
dataloaderの仕組みを理解するための簡易コード
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
function enqueuePostPromiseJob(fn) { | |
// Promise.resolve().then(fn) | |
// でも似たような動きになるが別のpromiseの解決に依存してexecを呼ばなければならない関数が同一の実行スケジュールから漏れてしまうため | |
// 次のフェーズの最速で呼ばれる nextTick で実行したほうが同一スケジュールでより多くの処理をすることができる。 | |
// これをコメントインすると `dependOtherAsyncFuncExec` が別のバッチスケジュールで呼ばれることが確認できる | |
// フェーズについて: https://blog.hiroppy.me/entry/nodejs-event-loop | |
Promise.resolve().then(() => { | |
// nextTick の理由: https://github.com/graphql/dataloader/issues/180 | |
process.nextTick(fn); | |
}); | |
} | |
const batchObjects = []; | |
function availableBatchObj() { | |
const batchObj = batchObjects.find(o => !o.isDispatched); | |
if (batchObj) { | |
return batchObj; | |
} | |
const newBatchObj = { | |
isScheduled: false, | |
isDispatched: false, | |
resolves: [], | |
args: [], | |
}; | |
batchObjects.push(newBatchObj); | |
return newBatchObj; | |
} | |
function exec(arg) { | |
const batchObj = availableBatchObj(); | |
batchObj.args.push(arg); | |
if (!batchObj.isScheduled) { | |
batchObj.isScheduled = true; | |
enqueuePostPromiseJob(() => dispatch(batchObj)); | |
} | |
return new Promise((resolve) => { | |
batchObj.resolves.push(resolve); | |
}); | |
} | |
async function dependOtherAsyncFuncExec(arg) { | |
const val = await new Promise((r) => r(5)); | |
return exec([arg, val]); | |
} | |
function dispatch(batchObj) { | |
batchObj.isDispatched = true; | |
console.log('複数の非同期関数を一括で解決:', batchObj.args); | |
for (let i = 0; i < batchObj.resolves.length; i++) { | |
batchObj.resolves[i](batchObj.args[i]); | |
} | |
} | |
async function main() { | |
const a = await exec(1); | |
printResult(a); | |
exec(2).then(printResult); | |
exec(3).then(printResult); | |
dependOtherAsyncFuncExec(4).then(printResult); | |
} | |
function printResult(val) { | |
console.log(` -> ${val}`); | |
} | |
main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment