JavaScriptã®Async Local StorageïŒALSïŒã掻çšããéåæã¢ããªã±ãŒã·ã§ã³ã«ãããå ç¢ãªã³ã³ããã¹ã管çãæ¢æ±ããŸãããªã¯ãšã¹ãåºæããŒã¿ã®è¿œè·¡ããŠãŒã¶ãŒã»ãã·ã§ã³ã®ç®¡çãéåæåŠçå šäœã®ãããã°ãæ¹åããæ¹æ³ãåŠã³ãŸãã
JavaScriptã®Async Local Storage: éåæç°å¢ã«ãããã³ã³ããã¹ã管çã®ç¿åŸ
éåæããã°ã©ãã³ã°ã¯ãçŸä»£ã®JavaScriptãç¹ã«ãµãŒããŒãµã€ãã¢ããªã±ãŒã·ã§ã³åãã®Node.jsãããŸããŸããã©ãŠã¶ã«ãããŠããåºæ¬çãªèŠçŽ ãšãªã£ãŠããŸãããããããªã¯ãšã¹ãããŠãŒã¶ãŒã»ãã·ã§ã³ããŸãã¯ãã©ã³ã¶ã¯ã·ã§ã³ã«åºæã®ããŒã¿ã§ããã³ã³ããã¹ãããéåæåŠçããŸããã§ç®¡çããããšã¯å°é£ãªå ŽåããããŸããç¹ã«è€éãªã¢ããªã±ãŒã·ã§ã³ã§ã¯ã颿°åŒã³åºããéããŠããŒã¿ãæž¡ããšãã£ãæšæºçãªææ³ã¯ãé¢åã§ãšã©ãŒãçºçãããããªãå¯èœæ§ããããŸããããã§ãAsync Local Storage (ALS) ã匷åãªè§£æ±ºçãšããŠç»å ŽããŸãã
Async Local Storage (ALS) ãšã¯äœãïŒ
Async Local Storage (ALS) ã¯ãç¹å®ã®éåæåŠçã«ããŒã«ã«ãªããŒã¿ãä¿åããæ¹æ³ãæäŸããŸããããã¯ãä»ã®ããã°ã©ãã³ã°èšèªã«ãããã¹ã¬ããããŒã«ã«ã¹ãã¬ãŒãžã®ãããªãã®ãšèããããšãã§ããŸãããJavaScriptã®ã·ã³ã°ã«ã¹ã¬ãããã€ãã³ãé§åã¢ãã«ã«åãããŠèª¿æŽãããŠããŸããALSã䜿çšãããšãçŸåšã®éåæå®è¡ã³ã³ããã¹ãã«ããŒã¿ãé¢é£ä»ããããšãã§ããåŒæ°ãšããŠæç€ºçã«æž¡ãããšãªããéåæåŒã³åºããã§ãŒã³å šäœã§ã¢ã¯ã»ã¹å¯èœã«ãªããŸãã
æ¬è³ªçã«ãALSã¯åãã³ã³ããã¹ãå ã§éå§ãããéåæåŠçãéããŠèªåçã«äŒæãããã¹ãã¬ãŒãžã¹ããŒã¹ãäœæããŸããããã«ãããã³ã³ããã¹ã管çãç°¡çŽ åãããéåæã®å¢çãè¶ããŠç¶æ ãç¶æããããã«å¿ èŠãªå®åçãªã³ãŒããå€§å¹ ã«åæžãããŸãã
ãªãAsync Local Storageã䜿çšããã®ãïŒ
ALSã¯ãéåæJavaScriptéçºã«ãããŠããã€ãã®äž»èŠãªå©ç¹ãæäŸããŸãã
- ã³ã³ããã¹ã管çã®ç°¡çŽ å: è€æ°ã®é¢æ°åŒã³åºããä»ããŠã³ã³ããã¹ã倿°ãæž¡ãå¿ èŠããªããªããã³ãŒãã®ç ©éããæžããå¯èªæ§ãåäžããŸãã
- ãããã°ã®æ¹å: éåæåŒã³åºãã¹ã¿ãã¯å šäœã§ãªã¯ãšã¹ãåºæã®ããŒã¿ãç°¡åã«è¿œè·¡ã§ãããããã°ãšãã©ãã«ã·ã¥ãŒãã£ã³ã°ã容æã«ãªããŸãã
- å®åã³ãŒãã®åæž: ã³ã³ããã¹ããæåã§äŒæãããå¿ èŠããªããªããããã¯ãªãŒã³ã§ä¿å®ããããã³ãŒãã«ãªããŸãã
- ããã©ãŒãã³ã¹ã®åäž: ã³ã³ããã¹ãã®äŒæã¯èªåçã«åŠçããããããæåã§ã®ã³ã³ããã¹ãåãæž¡ãã«äŒŽãããã©ãŒãã³ã¹ã®ãªãŒããŒããããæå°éã«æããããŸãã
- ã³ã³ããã¹ãã¢ã¯ã»ã¹ã®äžå å: ã³ã³ããã¹ãããŒã¿ã«ã¢ã¯ã»ã¹ããããã®åäžã§æç¢ºã«å®çŸ©ãããå ŽæãæäŸããã¢ã¯ã»ã¹ãšå€æŽãç°¡çŽ åããŸãã
Async Local Storageã®ãŠãŒã¹ã±ãŒã¹
ALSã¯ãéåæåŠçããŸããã§ãªã¯ãšã¹ãåºæã®ããŒã¿ã远跡ããå¿ èŠãããã·ããªãªã§ç¹ã«åœ¹ç«ã¡ãŸãã以äžã«äžè¬çãªãŠãŒã¹ã±ãŒã¹ãããã€ã瀺ããŸãã
1. ãŠã§ããµãŒããŒã§ã®ãªã¯ãšã¹ã远跡
ãŠã§ããµãŒããŒã§ã¯ãåä¿¡ããåãªã¯ãšã¹ããåå¥ã®éåæã³ã³ããã¹ããšããŠæ±ãããšãã§ããŸããALSã䜿çšããŠããªã¯ãšã¹ãIDããŠãŒã¶ãŒIDãèªèšŒããŒã¯ã³ããã®ä»ã®é¢é£ããŒã¿ãªã©ããªã¯ãšã¹ãåºæã®æ å ±ãä¿åã§ããŸããããã«ãããããã«ãŠã§ã¢ãã³ã³ãããŒã©ãŒãããŒã¿ããŒã¹ã¯ãšãªãªã©ããªã¯ãšã¹ããåŠçããã¢ããªã±ãŒã·ã§ã³ã®ã©ã®éšåããã§ããã®æ å ±ã«ç°¡åã«ã¢ã¯ã»ã¹ã§ããŸãã
äŸ (Node.jsãšExpress):
const express = require('express');
const { AsyncLocalStorage } = require('async_hooks');
const { v4: uuidv4 } = require('uuid');
const app = express();
const asyncLocalStorage = new AsyncLocalStorage();
app.use((req, res, next) => {
const requestId = uuidv4();
asyncLocalStorage.run(new Map(), () => {
asyncLocalStorage.getStore().set('requestId', requestId);
console.log(`ãªã¯ãšã¹ã ${requestId} ãéå§ãããŸãã`);
next();
});
});
app.get('/', (req, res) => {
const requestId = asyncLocalStorage.getStore().get('requestId');
console.log(`ãªã¯ãšã¹ã ${requestId} ãåŠçäž`);
res.send(`ããã«ã¡ã¯ããªã¯ãšã¹ãID: ${requestId}`);
});
app.listen(3000, () => {
console.log('ãµãŒããŒãããŒã3000ã§åŸ
æ©äž');
});
ãã®äŸã§ã¯ãåä¿¡ãªã¯ãšã¹ãããšã«äžæã®ãªã¯ãšã¹ãIDãå²ãåœãŠãããAsync Local Storageã«ä¿åãããŸãããã®IDã¯ããªã¯ãšã¹ããã³ãã©ãŒã®ã©ã®éšåããã§ãã¢ã¯ã»ã¹ã§ããã©ã€ããµã€ã¯ã«å šäœãéããŠãªã¯ãšã¹ãã远跡ã§ããŸãã
2. ãŠãŒã¶ãŒã»ãã·ã§ã³ç®¡ç
ALSã¯ãŠãŒã¶ãŒã»ãã·ã§ã³ã®ç®¡çã«ã䜿çšã§ããŸãããŠãŒã¶ãŒããã°ã€ã³ãããšããŠãŒã¶ãŒã®ã»ãã·ã§ã³ããŒã¿ïŒäŸïŒãŠãŒã¶ãŒIDãããŒã«ãæš©éïŒãALSã«ä¿åã§ããŸããããã«ãããåŒæ°ãšããŠæž¡ãããšãªãããããå¿ èŠãšããã¢ããªã±ãŒã·ã§ã³ã®ã©ã®éšåããã§ããŠãŒã¶ãŒã®ã»ãã·ã§ã³ããŒã¿ã«ç°¡åã«ã¢ã¯ã»ã¹ã§ããŸãã
äŸ:
const { AsyncLocalStorage } = require('async_hooks');
const asyncLocalStorage = new AsyncLocalStorage();
function authenticateUser(username, password) {
// èªèšŒãã·ãã¥ã¬ãŒã
if (username === 'user' && password === 'password') {
const userSession = { userId: 123, username: 'user', roles: ['admin'] };
asyncLocalStorage.run(new Map(), () => {
asyncLocalStorage.getStore().set('userSession', userSession);
console.log('ãŠãŒã¶ãŒãèªèšŒãããã»ãã·ã§ã³ãALSã«ä¿åãããŸãã');
return true;
});
return true;
} else {
return false;
}
}
function getUserSession() {
return asyncLocalStorage.getStore() ? asyncLocalStorage.getStore().get('userSession') : null;
}
function someAsyncOperation() {
return new Promise(resolve => {
setTimeout(() => {
const userSession = getUserSession();
if (userSession) {
console.log(`éåææäœ: ãŠãŒã¶ãŒID: ${userSession.userId}`);
resolve();
} else {
console.log('éåææäœ: ãŠãŒã¶ãŒã»ãã·ã§ã³ãèŠã€ãããŸãã');
resolve();
}
}, 100);
});
}
async function main() {
if (authenticateUser('user', 'password')) {
await someAsyncOperation();
} else {
console.log('èªèšŒã«å€±æããŸãã');
}
}
main();
ãã®äŸã§ã¯ãèªèšŒãæåãããšããŠãŒã¶ãŒã»ãã·ã§ã³ãALSã«ä¿åãããŸãããã®åŸã`someAsyncOperation`颿°ã¯ãåŒæ°ãšããŠæç€ºçã«æž¡ãããããšãªãããã®ã»ãã·ã§ã³ããŒã¿ã«ã¢ã¯ã»ã¹ã§ããŸãã
3. ãã©ã³ã¶ã¯ã·ã§ã³ç®¡ç
ããŒã¿ããŒã¹ãã©ã³ã¶ã¯ã·ã§ã³ã§ã¯ãALSã䜿çšããŠãã©ã³ã¶ã¯ã·ã§ã³ãªããžã§ã¯ããä¿åã§ããŸããããã«ããããã©ã³ã¶ã¯ã·ã§ã³ã«åå ããã¢ããªã±ãŒã·ã§ã³ã®ã©ã®éšåããã§ããã©ã³ã¶ã¯ã·ã§ã³ãªããžã§ã¯ãã«ã¢ã¯ã»ã¹ã§ãããã¹ãŠã®æäœãåããã©ã³ã¶ã¯ã·ã§ã³ã¹ã³ãŒãå ã§å®è¡ãããããšãä¿èšŒãããŸãã
4. ãã®ã³ã°ãšç£æ»
ALSã¯ããã®ã³ã°ãç£æ»ã®ç®çã§ã³ã³ããã¹ãåºæã®æ å ±ãä¿åããããã«äœ¿çšã§ããŸããããšãã°ããŠãŒã¶ãŒIDããªã¯ãšã¹ãIDãã¿ã€ã ã¹ã¿ã³ããALSã«ä¿åãããããã®æ å ±ããã°ã¡ãã»ãŒãžã«å«ããããšãã§ããŸããããã«ããããŠãŒã¶ãŒã®ã¢ã¯ãã£ããã£ã远跡ããæœåšçãªã»ãã¥ãªãã£åé¡ãç¹å®ãããããªããŸãã
Async Local Storageã®äœ¿ç𿹿³
Async Local Storageã®äœ¿çšã«ã¯ãäž»ã«3ã€ã®ã¹ãããããããŸãã
- AsyncLocalStorageã€ã³ã¹ã¿ã³ã¹ã®äœæ: `AsyncLocalStorage`ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããŸãã
- ã³ã³ããã¹ãå ã§ã®ã³ãŒãã®å®è¡: `run()`ã¡ãœããã䜿çšããŠãç¹å®ã®ã³ã³ããã¹ãå ã§ã³ãŒããå®è¡ããŸãã`run()`ã¡ãœããã¯ãã¹ãã¢ïŒéåžžã¯MapãŸãã¯ãªããžã§ã¯ãïŒãšã³ãŒã«ããã¯é¢æ°ã®2ã€ã®åŒæ°ãåããŸããã¹ãã¢ã¯ãã³ãŒã«ããã¯é¢æ°å ã§éå§ããããã¹ãŠã®éåææäœã§å©çšå¯èœã«ãªããŸãã
- ã¹ãã¢ãžã®ã¢ã¯ã»ã¹: `getStore()`ã¡ãœããã䜿çšããŠãéåæã³ã³ããã¹ãå ããã¹ãã¢ã«ã¢ã¯ã»ã¹ããŸãã
äŸ:
const { AsyncLocalStorage } = require('async_hooks');
const asyncLocalStorage = new AsyncLocalStorage();
function doSomethingAsync() {
return new Promise(resolve => {
setTimeout(() => {
const value = asyncLocalStorage.getStore().get('myKey');
console.log('ALSããã®å€:', value);
resolve();
}, 500);
});
}
async function main() {
asyncLocalStorage.run(new Map(), async () => {
asyncLocalStorage.getStore().set('myKey', 'ALSããã®ããã«ã¡ã¯ïŒ');
await doSomethingAsync();
});
}
main();
AsyncLocalStorage API
`AsyncLocalStorage`ã¯ã©ã¹ã¯ã以äžã®ã¡ãœãããæäŸããŸãã
- constructor(): æ°ããAsyncLocalStorageã€ã³ã¹ã¿ã³ã¹ãäœæããŸãã
- run(store, callback, ...args): æå®ãããã¹ãã¢ãå©çšå¯èœãªã³ã³ããã¹ãå ã§ãæäŸãããã³ãŒã«ããã¯é¢æ°ãå®è¡ããŸããã¹ãã¢ã¯éåžžã`Map`ãŸãã¯ãã¬ãŒã³ãªJavaScriptãªããžã§ã¯ãã§ããã³ãŒã«ããã¯å ã§éå§ãããéåææäœã¯ããã®ã³ã³ããã¹ããç¶æ¿ããŸãã远å ã®åŒæ°ãã³ãŒã«ããã¯é¢æ°ã«æž¡ãããšãã§ããŸãã
- getStore(): çŸåšã®éåæã³ã³ããã¹ãã®çŸåšã®ã¹ãã¢ãè¿ããŸããçŸåšã®ã³ã³ããã¹ãã«é¢é£ä»ããããã¹ãã¢ããªãå Žåã¯`undefined`ãè¿ããŸãã
- disable(): AsyncLocalStorageã€ã³ã¹ã¿ã³ã¹ãç¡å¹ã«ããŸããç¡å¹ã«ãªããšã`run()`ãš`getStore()`ã¯æ©èœããªããªããŸãã
èæ ®äºé ãšãã¹ããã©ã¯ãã£ã¹
ALSã¯åŒ·åãªããŒã«ã§ãããæ éã«äœ¿çšããããšãéèŠã§ãã以äžã«ããã€ãã®èæ ®äºé ãšãã¹ããã©ã¯ãã£ã¹ã瀺ããŸãã
- é床ã®äœ¿çšãé¿ãã: ãã¹ãŠã«ALSã䜿çšããªãã§ãã ãããéåæã®å¢çãè¶ããŠã³ã³ããã¹ãã远跡ããå¿ èŠãããå Žåã«ã®ã¿äœ¿çšããŠãã ãããã³ã³ããã¹ããéåæåŒã³åºãã§äŒæãããå¿ èŠããªãå Žåã¯ãéåžžã®å€æ°ã®ãããªããåçŽãªè§£æ±ºçãæ€èšããŠãã ããã
- ããã©ãŒãã³ã¹: ALSã¯äžè¬çã«å¹ççã§ãããé床ã®äœ¿çšã¯ããã©ãŒãã³ã¹ã«åœ±é¿ãäžããå¯èœæ§ããããŸããå¿ èŠã«å¿ããŠã³ãŒããæž¬å®ããæé©åããŠãã ãããALSã«å ¥ããã¹ãã¢ã®ãµã€ãºã«æ³šæããŠãã ãããç¹ã«å€ãã®éåææäœãéå§ãããå Žåã倧ããªãªããžã§ã¯ãã¯ããã©ãŒãã³ã¹ã«åœ±é¿ãäžããå¯èœæ§ããããŸãã
- ã³ã³ããã¹ã管ç: ã¹ãã¢ã®ã©ã€ããµã€ã¯ã«ãé©åã«ç®¡çããããã«ããŠãã ããããªã¯ãšã¹ããŸãã¯ã»ãã·ã§ã³ããšã«æ°ããã¹ãã¢ãäœæããäžèŠã«ãªã£ããã¹ãã¢ãã¯ãªãŒã³ã¢ããããŠãã ãããALSèªäœã¯ã¹ã³ãŒãã®ç®¡çã«åœ¹ç«ã¡ãŸãããã¹ãã¢*å *ã®ããŒã¿ã¯äŸç¶ãšããŠé©åãªåŠçãšã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãå¿ èŠãšããŸãã
- ãšã©ãŒãã³ããªã³ã°: ãšã©ãŒãã³ããªã³ã°ã«æ³šæããŠãã ãããéåææäœå ã§ãšã©ãŒãçºçããå Žåãã³ã³ããã¹ãã倱ãããå¯èœæ§ããããŸããtry-catchãããã¯ã䜿çšããŠãšã©ãŒãåŠçããã³ã³ããã¹ããé©åã«ç¶æãããããã«ããããšãæ€èšããŠãã ããã
- ãããã°: ALSããŒã¹ã®ã¢ããªã±ãŒã·ã§ã³ã®ãããã°ã¯å°é£ãªå ŽåããããŸãããããã°ããŒã«ãšãã®ã³ã°ã䜿çšããŠãå®è¡ãããŒã远跡ããæœåšçãªåé¡ãç¹å®ããŠãã ããã
- äºææ§: ALSã¯Node.jsããŒãžã§ã³14.5.0以éã§å©çšå¯èœã§ãã䜿çšããåã«ãç°å¢ãALSããµããŒãããŠããããšã確èªããŠãã ãããå€ãããŒãžã§ã³ã®Node.jsã§ã¯ãcontinuation-local storageïŒCLSïŒãªã©ã®ä»£æ¿ãœãªã¥ãŒã·ã§ã³ã®äœ¿çšãæ€èšããŠãã ããããã ãããããã¯ããã©ãŒãã³ã¹ç¹æ§ãAPIãç°ãªãå ŽåããããŸãã
Async Local Storageã®ä»£æ¿ææ®µ
ALSãå°å ¥ãããåã¯ãéçºè ã¯éåæJavaScriptã§ã®ã³ã³ããã¹ã管çã«ä»ã®ææ³ã«é ŒãããšããããããŸããã以äžã«äžè¬çãªä»£æ¿ææ®µãããã€ã瀺ããŸãã
- æç€ºçãªã³ã³ããã¹ãã®åãæž¡ã: åŒã³åºããã§ãŒã³å ã®ãã¹ãŠã®é¢æ°ã«åŒæ°ãšããŠã³ã³ããã¹ã倿°ãæž¡ããŸãããã®ã¢ãããŒãã¯åçŽã§ãããè€éãªã¢ããªã±ãŒã·ã§ã³ã§ã¯é¢åã§ãšã©ãŒãçºçãããããªãå¯èœæ§ããããŸãããŸããã³ã³ããã¹ãããŒã¿ã倿Žãããšå€ãã®é¢æ°ã®ã·ã°ããã£ã倿Žããå¿ èŠãããããããªãã¡ã¯ã¿ãªã³ã°ãå°é£ã«ãªããŸãã
- Continuation-Local Storage (CLS): CLSã¯ALSãšé¡äŒŒã®æ©èœãæäŸããŸãããç°ãªãã¡ã«ããºã ã«åºã¥ããŠããŸããCLSã¯ã¢ã³ããŒãããã䜿çšããŠéåææäœãã€ã³ã¿ãŒã»ããããã³ã³ããã¹ããäŒæãããŸãããã®ã¢ãããŒãã¯ããè€éã§ãããã©ãŒãã³ã¹ã«åœ±é¿ãäžããå¯èœæ§ããããŸãã
- ã©ã€ãã©ãªãšãã¬ãŒã ã¯ãŒã¯: äžéšã®ã©ã€ãã©ãªããã¬ãŒã ã¯ãŒã¯ã¯ãç¬èªã®ã³ã³ããã¹ã管çã¡ã«ããºã ãæäŸããŠããŸããããšãã°ãExpress.jsã¯ãªã¯ãšã¹ãåºæã®ããŒã¿ã管çããããã®ããã«ãŠã§ã¢ãæäŸããŠããŸãã
ãããã®ä»£æ¿ææ®µã¯ç¹å®ã®ç¶æ³ã§åœ¹ç«ã€ããšããããŸãããALSã¯éåæJavaScriptã§ã®ã³ã³ããã¹ã管çã«å¯ŸããŠããããšã¬ã¬ã³ãã§å¹ççãªãœãªã¥ãŒã·ã§ã³ãæäŸããŸãã
çµè«
Async Local Storage (ALS) ã¯ãéåæJavaScriptã¢ããªã±ãŒã·ã§ã³ã§ã³ã³ããã¹ãã管çããããã®åŒ·åãªããŒã«ã§ããç¹å®ã®éåææäœã«ããŒã«ã«ãªããŒã¿ãä¿åããæ¹æ³ãæäŸããããšã§ãALSã¯ã³ã³ããã¹ã管çãç°¡çŽ åãããããã°ãæ¹åããå®åã³ãŒããåæžããŸãããŠã§ããµãŒããŒã®æ§ç¯ããŠãŒã¶ãŒã»ãã·ã§ã³ã®ç®¡çãããŒã¿ããŒã¹ãã©ã³ã¶ã¯ã·ã§ã³ã®åŠçãªã©ãã©ã®ãããªå Žåã§ããALSã¯ããã¯ãªãŒã³ã§ãä¿å®ãããããå¹ççãªã³ãŒããæžãã®ã«åœ¹ç«ã¡ãŸãã
éåæããã°ã©ãã³ã°ã¯JavaScriptã§ãŸããŸãæ®åããŠãããALSã®ãããªããŒã«ãçè§£ããããšã¯ãŸããŸãéèŠã«ãªã£ãŠããŸãããã®é©åãªäœ¿çšæ³ãšéçãçè§£ããããšã§ãéçºè ã¯ãäžçäžã®å€æ§ãªãŠãŒã¶ãŒããŒãºã«åãããŠã¹ã±ãŒãªã³ã°ããã³é©å¿ã§ãããããå ç¢ã§ç®¡çããããã¢ããªã±ãŒã·ã§ã³ãäœæã§ããŸããããªãã®ãããžã§ã¯ãã§ALSã詊ããŠã¿ãŠããããéåæã¯ãŒã¯ãããŒãã©ã®ããã«ç°¡çŽ åããå šäœçãªã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£ãæ¹åã§ããããçºèŠããŠãã ããã