JavaScriptã®`using`æãæ·±ãæãäžããå ç¢ãªãªãœãŒã¹ç®¡çã解説ãäŸå€å®å šãªã¯ãªãŒã³ã¢ããä¿èšŒã«ãããçŸä»£ã®ãŠã§ãã¢ããªããµãŒãã¹ã®ä¿¡é Œæ§ãäžçäžã§é«ããæ¹æ³ãæ¢ããŸãã
JavaScriptã®`using`æïŒäŸå€å®å šãªãªãœãŒã¹ç®¡çãšã¯ãªãŒã³ã¢ããä¿èšŒã®åŸ¹åºè§£èª¬
ãã¡ã€ã«ã·ã¹ãã ããããã¯ãŒã¯æ¥ç¶ããããŒã¿ããŒã¹ãè€éãªããã€ã¹ã€ã³ã¿ãŒãã§ãŒã¹ãŸã§ãã¢ããªã±ãŒã·ã§ã³ã倿°ã®å€éšã·ã¹ãã ãšé£æºãããœãããŠã§ã¢éçºã®ãã€ãããã¯ãªäžçã«ãããŠããªãœãŒã¹ã®ç¶¿å¯ãªç®¡çã¯æ¥µããŠéèŠã§ããè§£æŸãããªããªãœãŒã¹ã¯ãããã©ãŒãã³ã¹ã®äœäžãã¡ã¢ãªãªãŒã¯ãã·ã¹ãã äžå®å®æ§ãããã«ã¯ã»ãã¥ãªãã£è匱æ§ãšãã£ãæ·±å»ãªåé¡ãåŒãèµ·ããå¯èœæ§ããããŸããJavaScriptã¯åçã«é²åããŠããŸããããæŽå²çã«ãªãœãŒã¹ã®ã¯ãªãŒã³ã¢ããã¯æåã®`try...finally`ãããã¯ã«äŸåããããšãå€ãããã®ãã¿ãŒã³ã¯å¹æçã§ãããã®ã®ãç¹ã«è€éãªéåææäœããã¹ãããããªãœãŒã¹å²ãåœãŠãæ±ãå Žåãåé·ã§ãšã©ãŒãçºçãããããä¿å®ãå°é£ã«ãªããšãã課é¡ããããŸããã
`using`æãšé¢é£ãã`Symbol.dispose`ããã³`Symbol.asyncDispose`ãããã³ã«ã®å°å ¥ã¯ãJavaScriptã«ãšã£ãŠå€§ããªé²æ©ãæå³ããŸããC#ã®`using`ãPythonã®`with`ãJavaã®`try-with-resources`ãšãã£ãä»ã®ç¢ºç«ãããããã°ã©ãã³ã°èšèªã®åæ§ã®æ§é ã«è§Šçºããããã®æ©èœã¯ããªãœãŒã¹ã管çããããã®å®£èšçã§å ç¢ãã€éåžžã«å®å šãªã¡ã«ããºã ãæäŸããŸãããã®æ žãšãªãã®ã¯ã`using`æããäŸå€ãã¹ããŒãããã·ããªãªãå«ããã¹ã³ãŒããã©ã®ããã«çµäºãããã«ãããããããªãœãŒã¹ãã¹ã³ãŒããé¢ãããšããã«é©åã«ã¯ãªãŒã³ã¢ããïŒãç Žæ£ãïŒãããããšãä¿èšŒãããšããç¹ã§ããæ¬èšäºã§ã¯ã`using`æã®å æ¬çãªæ¢æ±ã«çæãããã®ã¡ã«ããºã ãåæããå®çšçãªäŸãéããŠãã®åšåãå®èšŒããã°ããŒãã«ãªãªãŒãã£ãšã³ã¹åãã®ããä¿¡é Œæ§ãé«ããä¿å®å¯èœã§ãäŸå€å®å šãªJavaScriptã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããäžã§ã®ãã®æ·±é ãªåœ±é¿ã匷調ããŸãã
ãœãããŠã§ã¢ã«ããããªãœãŒã¹ç®¡çã®æ°žç¶çãªèª²é¡
ãœãããŠã§ã¢ã¢ããªã±ãŒã·ã§ã³ãèªå·±å®çµåã§ããããšã¯çšã§ãããããã¯åžžã«ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ãä»ã®ãµãŒãã¹ãããã³å€éšããŒããŠã§ã¢ãšé£æºããŠããŸãããããã®é£æºã«ã¯ããã°ãã°ããªãœãŒã¹ãã®ååŸãšè§£æŸã䌎ããŸãããªãœãŒã¹ãšã¯ãæéã®å®¹éãŸãã¯ç¶æ ãä¿æããåé¡ãé²ãããã«æç€ºçãªè§£æŸãå¿ èŠãšãããããããã®ãæããŸãã
ã¯ãªãŒã³ã¢ãããå¿ èŠãªãªãœãŒã¹ã®äžè¬çãªäŸïŒ
- ãã¡ã€ã«ãã³ãã«ïŒãã¡ã€ã«ãèªã¿æžãããéããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã¯ããã¡ã€ã«ãã³ãã«ããæäŸããŸãããã®ãã³ãã«ãéãå¿ãããšããã¡ã€ã«ãããã¯ãããããä»ã®ããã»ã¹ããã®ã¢ã¯ã»ã¹ã劚ããããããã·ã¹ãã ã¡ã¢ãªãæ¶è²»ãããããå¯èœæ§ããããŸãã
- ãããã¯ãŒã¯ãœã±ãã/æ¥ç¶ïŒãªã¢ãŒããµãŒããŒãžã®æ¥ç¶ïŒäŸïŒHTTPãWebSocketããŸãã¯çã®TCPçµç±ïŒã確ç«ãããšããããã¯ãŒã¯ãœã±ãããéãããŸãããããã®æ¥ç¶ã¯ãããã¯ãŒã¯ããŒããšã·ã¹ãã ã¡ã¢ãªãæ¶è²»ããŸããé©åã«éããããªãå ŽåããããŒãæ¯æžãããã¢ããªã±ãŒã·ã§ã³ããã©ãŒãã³ã¹ã劚ããéãããŸãŸã®æ¥ç¶ãæ®ãåå ãšãªããŸãã
- ããŒã¿ããŒã¹æ¥ç¶ïŒããŒã¿ããŒã¹ã«æ¥ç¶ãããšããµãŒããŒåŽã®ãªãœãŒã¹ãšã¯ã©ã€ã¢ã³ãåŽã®ã¡ã¢ãªãæ¶è²»ããŸããæ¥ç¶ããŒã«ã¯äžè¬çã§ãããåã ã®æ¥ç¶ã¯äŸç¶ãšããŠããŒã«ã«æ»ãããæç€ºçã«éããå¿ èŠããããŸãã
- ããã¯ãšãã¥ãŒããã¯ã¹ïŒäžŠè¡ããã°ã©ãã³ã°ã§ã¯ãå ±æãªãœãŒã¹ãžã®åæã¢ã¯ã»ã¹ãä¿è·ããããã«ããã¯ã䜿çšãããŸããããã¯ãååŸãããŠãè§£æŸãããªãå Žåããããããã¯ãåŒãèµ·ãããã¢ããªã±ãŒã·ã§ã³å šäœã®ç¹å®ã®éšåã忢ããå¯èœæ§ããããŸãã
- ã¿ã€ããŒãšã€ãã³ããªã¹ããŒïŒåžžã«æããã§ã¯ãããŸããããé·æéå®è¡ããã`setInterval`ã¿ã€ããŒããã°ããŒãã«ãªããžã§ã¯ãïŒ`window`ã`document`ãªã©ïŒã«ã¢ã¿ããããããŸãŸåé€ãããªãã€ãã³ããªã¹ããŒã¯ããªããžã§ã¯ãã®ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã劚ããã¡ã¢ãªãªãŒã¯ã«ã€ãªããå¯èœæ§ããããŸãã
- å°çšã®Web WorkerãŸãã¯iFrameïŒãããã®ç°å¢ã¯ãã¡ã¢ãªãCPUãµã€ã¯ã«ãè§£æŸããããã«æç€ºçãªçµäºãå¿ èŠãªç¹å®ã®ãªãœãŒã¹ãã³ã³ããã¹ãããã°ãã°ååŸããŸãã
æ ¹æ¬çãªåé¡ã¯ãäºæãã¬ç¶æ³ãçºçããå Žåã§ãããããã®ãªãœãŒã¹ãåžžã«è§£æŸãããããšãä¿èšŒããããšã«ãããŸããããã§ãäŸå€å®å šæ§ãéèŠã«ãªããŸãã
ãªãœãŒã¹ã¯ãªãŒã³ã¢ããã«ãããåŸæ¥ã®`try...finally`ã®éç
`using`æãç»å Žããåã¯ãJavaScriptéçºè ã¯äž»ã«`try...finally`æ§æã«äŸåããŠã¯ãªãŒã³ã¢ãããä¿èšŒããŠããŸããã`finally`ãããã¯ã¯ã`try`ãããã¯å ã§äŸå€ãçºçãããã`try`ãããã¯ãæ£åžžã«å®äºãããã«é¢ãããå®è¡ãããŸãã
ãã¡ã€ã«ãæ±ãä»®æ³çãªåææäœãèããŠã¿ãŸãããïŒ
function processFile(filePath) {
let fileHandle;
try {
fileHandle = openFile(filePath, 'r');
// Perform operations with fileHandle
const content = readFile(fileHandle);
console.log(`File content: ${content}`);
// Potentially throw an error here
if (content.includes('error')) {
throw new Error('Specific error found in file content');
}
} finally {
if (fileHandle) {
closeFile(fileHandle); // Guaranteed cleanup
console.log('File handle closed.');
}
}
}
// Assume openFile, readFile, closeFile are synchronous mock functions
const mockFiles = {};
function openFile(path, mode) {
console.log(`Opening file: ${path}`);
if (mockFiles[path]) return mockFiles[path];
const newHandle = { id: Math.random(), path, mode, isOpen: true, content: 'Some important data for processing.' };
if (path === 'errorFile.txt') {
newHandle.content = 'This file contains an error string.';
}
mockFiles[path] = newHandle;
return newHandle;
}
function readFile(handle) {
if (!handle || !handle.isOpen) throw new Error('Invalid file handle.');
console.log(`Reading from file: ${handle.path}`);
return handle.content;
}
function closeFile(handle) {
if (handle) {
console.log(`Closing file: ${handle.path}`);
handle.isOpen = false;
delete mockFiles[handle.path]; // Cleanup mock
}
}
try {
processFile('data.txt');
console.log('---');
processFile('errorFile.txt'); // This will throw
} catch (e) {
console.error(`Caught an error: ${e.message}`);
}
// Expected output will show 'File handle closed.' even for the error case.
`try...finally`ã¯æ©èœããŸãããããã€ãã®æ¬ ç¹ããããŸãïŒ
- åé·æ§ïŒãã¹ãŠã®ãªãœãŒã¹ã«ã€ããŠã`try`ãããã¯ã®å€ã§å®£èšããåæåãã䜿çšãããã®åŸã`finally`ãããã¯ã§ãã®ååšãæç€ºçã«ãã§ãã¯ããŠããç Žæ£ããå¿ èŠããããŸãããã®ãã€ã©ãŒãã¬ãŒãã¯ãç¹ã«è€æ°ã®ãªãœãŒã¹ãæ±ãå Žåã«èç©ãããŸãã
- ãã¹ãã®è€éãïŒè€æ°ã®çžäºäŸåãããªãœãŒã¹ã管çããå Žåã`try...finally`ãããã¯ã¯æ·±ããã¹ããããã¡ã§ãå¯èªæ§ãèããæãªããã¯ãªãŒã³ã¢ããäžã«ãªãœãŒã¹ãèŠèœãšããããšã©ãŒã®å¯èœæ§ãé«ããŸãã
- ãšã©ãŒã®çºçããããïŒ`finally`ãããã¯ã§`if (resource)`ã®ãã§ãã¯ãå¿ããããã¯ãªãŒã³ã¢ããããžãã¯ã誀ã£ãŠé 眮ããããããšã埮åŠãªãã°ããªãœãŒã¹ãªãŒã¯ã«ã€ãªããå¯èœæ§ããããŸãã
- éåæã®èª²é¡ïŒ`try...finally`ã䜿çšããéåæãªãœãŒã¹ç®¡çã¯ããã«è€éã§ã`finally`ãããã¯å ã§Promiseãš`await`ãæ éã«åŠçããå¿ èŠããããç«¶åç¶æ ãæªåŠçã®æåŠãåŒãèµ·ããå¯èœæ§ããããŸãã
JavaScriptã®`using`æã®ç޹ä»ïŒãªãœãŒã¹ã¯ãªãŒã³ã¢ããã®ãã©ãã€ã ã·ãã
JavaScriptãžã®æè¿ãã¹ã远å ã§ãã`using`æã¯ãèªåãªãœãŒã¹ç Žæ£ã®ããã®å®£èšçãªæ§æãæäŸããããšã§ããããã®åé¡ããšã¬ã¬ã³ãã«è§£æ±ºããããã«èšèšãããŠããŸãããDisposableããããã³ã«ã«æºæ ãããã¹ãŠã®ãªããžã§ã¯ãããã¹ã³ãŒããã©ã®ããã«çµäºãããã«é¢ãããããã®ã¹ã³ãŒãã®çµäºæã«æ£ããã¯ãªãŒã³ã¢ãããããããšãä¿èšŒããŸãã
æ žãšãªãèãæ¹ïŒèªåçã§äŸå€å®å šãªç Žæ£
`using`æã¯ãä»ã®èšèªã«ãããäžè¬çãªãã¿ãŒã³ããçæ³ãåŸãŠããŸãïŒ
- C#ã®`using`æïŒ`IDisposable`ãå®è£ ãããªããžã§ã¯ãã®`Dispose()`ãèªåçã«åŒã³åºããŸãã
- Pythonã®`with`æïŒã³ã³ããã¹ãã管çãã`__enter__`ããã³`__exit__`ã¡ãœãããåŒã³åºããŸãã
- Javaã®`try-with-resources`ïŒ`AutoCloseable`ãå®è£ ãããªããžã§ã¯ãã®`close()`ãèªåçã«åŒã³åºããŸãã
JavaScriptã®`using`æã¯ããã®åŒ·åãªãã©ãã€ã ããŠã§ãã«ãããããŸããããã¯ãåæã¯ãªãŒã³ã¢ããã®ããã®`Symbol.dispose`ããŸãã¯éåæã¯ãªãŒã³ã¢ããã®ããã®`Symbol.asyncDispose`ã®ãããããå®è£ ãããªããžã§ã¯ãã«å¯ŸããŠåäœããŸãã`using`宣èšããã®ãããªãªããžã§ã¯ããåæåãããšãã©ã³ã¿ã€ã ã¯ãããã¯ãçµäºãããšãã«ãããããã®ç Žæ£ã¡ãœãããžã®åŒã³åºããèªåçã«ã¹ã±ãžã¥ãŒã«ããŸãããã®ã¡ã«ããºã ã¯ã`using`ãããã¯ãããšã©ãŒãäŒæããå Žåã§ãã¯ãªãŒã³ã¢ãããä¿èšŒããããããä¿¡ããããªãã»ã©å ç¢ã§ãã
`Disposable`ããã³`AsyncDisposable`ãããã³ã«
ãªããžã§ã¯ãã`using`æã§äœ¿çšå¯èœã§ããããã«ã¯ã以äžã®2ã€ã®ãããã³ã«ã®ããããã«æºæ ããŠããå¿ èŠããããŸãïŒ
- `Disposable`ãããã³ã«ïŒåæã¯ãªãŒã³ã¢ããçšïŒïŒãªããžã§ã¯ãã`Symbol.dispose`çµç±ã§ã¢ã¯ã»ã¹å¯èœãªã¡ãœãããæã£ãŠããå Žåããã®ãããã³ã«ãå®è£ ããŸãããã®ã¡ãœããã¯ããªãœãŒã¹ã«å¿ èŠãªåæã¯ãªãŒã³ã¢ãããå®è¡ããåŒæ°ãªãã®é¢æ°ã§ããå¿ èŠããããŸãã
class SyncResource {
constructor(name) {
this.name = name;
console.log(`SyncResource '${this.name}' acquired.`);
}
[Symbol.dispose]() {
console.log(`SyncResource '${this.name}' disposed synchronously.`);
}
doWork() {
console.log(`SyncResource '${this.name}' performing work.`);
if (this.name === 'errorResource') {
throw new Error(`Error during work for ${this.name}`);
}
}
}
- `AsyncDisposable`ãããã³ã«ïŒéåæã¯ãªãŒã³ã¢ããçšïŒïŒãªããžã§ã¯ãã`Symbol.asyncDispose`çµç±ã§ã¢ã¯ã»ã¹å¯èœãªã¡ãœãããæã£ãŠããå Žåããã®ãããã³ã«ãå®è£ ããŸãããã®ã¡ãœããã¯ãéåæã¯ãªãŒã³ã¢ãããå®äºãããšãã«è§£æ±ºããã`PromiseLike`ïŒäŸïŒ`Promise`ïŒãè¿ãåŒæ°ãªãã®é¢æ°ã§ããå¿ èŠããããŸããããã¯ãI/Oã䌎ãå¯èœæ§ã®ãããããã¯ãŒã¯æ¥ç¶ã®ã¯ããŒãºããã©ã³ã¶ã¯ã·ã§ã³ã®ã³ããããªã©ã®æäœã«ãšã£ãŠéèŠã§ãã
class AsyncResource {
constructor(id) {
this.id = id;
console.log(`AsyncResource '${this.id}' acquired.`);
}
async [Symbol.asyncDispose]() {
console.log(`AsyncResource '${this.id}' initiating async disposal...`);
await new Promise(resolve => setTimeout(resolve, 50)); // Simulate async operation
console.log(`AsyncResource '${this.id}' disposed asynchronously.`);
}
async fetchData() {
console.log(`AsyncResource '${this.id}' fetching data.`);
await new Promise(resolve => setTimeout(resolve, 20));
return `Data from ${this.id}`;
}
}
ãããã®ã·ã³ãã«ã`Symbol.dispose`ãš`Symbol.asyncDispose`ã¯ã`Symbol.iterator`ãšåæ§ã«ããªããžã§ã¯ãã®ç¹å®ã®æ¯ãèãå¥çŽã瀺ãJavaScriptã®well-knownã·ã³ãã«ã§ãã
æ§æãšåºæ¬çãªäœ¿çšæ³
`using`æã®æ§æã¯éåžžã«ã·ã³ãã«ã§ãã`const`ã`let`ããŸãã¯`var`宣èšãšéåžžã«ãã䌌ãŠããŸããã`using`ãŸãã¯`await using`ããã¬ãã£ãã¯ã¹ãšããŠä»ããŸãã
// Synchronous using
function demonstrateSyncUsing() {
using resourceA = new SyncResource('first'); // resourceA will be disposed when this block exits
resourceA.doWork();
if (Math.random() > 0.5) {
console.log('Exiting early due to condition.');
return; // resourceA is still disposed
}
// Nested using
{
using resourceB = new SyncResource('nested'); // resourceB disposed when inner block exits
resourceB.doWork();
} // resourceB disposed here
console.log('Continuing with resourceA.');
} // resourceA disposed here
demonstrateSyncUsing();
console.log('---');
try {
function demonstrateSyncUsingWithError() {
using errorResource = new SyncResource('errorResource');
errorResource.doWork(); // This will throw an error
console.log('This line will not be reached.');
} // errorResource is guaranteed to be disposed BEFORE the error propagates out
demonstrateSyncUsingWithError();
} catch (e) {
console.error(`Caught error from demonstrateSyncUsingWithError: ${e.message}`);
}
ãªãœãŒã¹ç®¡çãã©ãã»ã©ç°¡æœã§æç¢ºã«ãªããã«æ³šç®ããŠãã ããã`resourceA`ã`using`ã§å®£èšããããšã¯ãJavaScriptã©ã³ã¿ã€ã ã«ããããªãç¶æ³ã§ããå²ããããã¯ãçµäºãããšãã«`resourceA`ãã¯ãªãŒã³ã¢ãããããããšãä¿èšŒããããšäŒããŸããããã¯ããã¹ããããã¹ã³ãŒãå ã®`resourceB`ã«ãåæ§ã«é©çšãããŸãã
`using`ã«ããäŸå€å®å šæ§ã®å®è·µ
`using`æã®äž»ãªå©ç¹ã¯ããã®å ç¢ãªäŸå€å®å šæ§ä¿èšŒã§ãã`using`ãããã¯å ã§äŸå€ãçºçããå Žåãé¢é£ãã`Symbol.dispose`ãŸãã¯`Symbol.asyncDispose`ã¡ãœããã¯ãäŸå€ãã³ãŒã«ã¹ã¿ãã¯ãããã«äŒæããåã«ã確å®ã«åŒã³åºãããŸããããã«ããããšã©ãŒãã¯ãªãŒã³ã¢ããããžãã¯ã«å°éããã«æ©ãã«é¢æ°ãçµäºããå Žåã«çºçããå¯èœæ§ã®ãããªãœãŒã¹ãªãŒã¯ãé²ããŸãã
äŸå€åŠçã®ããã®`using`ãšæå`try...finally`ã®æ¯èŒ
ãã¡ã€ã«åŠçã®äŸãããŸã`try...finally`ãã¿ãŒã³ã§ã次ã«`using`ã䜿ã£ãŠåæ€èšããŠã¿ãŸãããã
æåã®`try...finally`ïŒåæïŒïŒ
// Using the same mock openFile, readFile, closeFile from above (re-declared for context)
const mockFiles = {};
function openFile(path, mode) {
console.log(`Opening file: ${path}`);
if (mockFiles[path]) return mockFiles[path];
const newHandle = { id: Math.random(), path, mode, isOpen: true, content: 'Some important data for processing.' };
if (path === 'errorFile.txt') {
newHandle.content = 'This file contains an error string.';
}
mockFiles[path] = newHandle;
return newHandle;
}
function readFile(handle) {
if (!handle || !handle.isOpen) throw new Error('Invalid file handle.');
console.log(`Reading from file: ${handle.path}`);
return handle.content;
}
function closeFile(handle) {
if (handle) {
console.log(`Closing file: ${handle.path}`);
handle.isOpen = false;
delete mockFiles[handle.path]; // Cleanup mock
}
}
function processFileManual(filePath) {
let fileHandle;
try {
fileHandle = openFile(filePath, 'r');
const content = readFile(fileHandle);
console.log(`Processing content from '${filePath}': ${content.substring(0, 20)}...`);
// Simulate an error based on content
if (content.includes('error')) {
throw new Error(`Detected problematic content in '${filePath}'.`);
}
return content.length;
} finally {
if (fileHandle) {
closeFile(fileHandle);
console.log(`Resource '${filePath}' cleaned up via finally.`);
}
}
}
console.log('--- Demonstrating manual try...finally cleanup ---');
try {
processFileManual('safe.txt'); // Assume 'safe.txt' has no 'error'
processFileManual('errorFile.txt'); // This will throw
} catch (e) {
console.error(`Error caught outside: ${e.message}`);
}
console.log('--- End manual try...finally ---');
ãã®äŸã§ã¯ã`processFileManual('errorFile.txt')`ããšã©ãŒãã¹ããŒããå Žåã§ãã`finally`ãããã¯ã¯`fileHandle`ãæ£ããéããŸããã¯ãªãŒã³ã¢ããããžãã¯ã¯æç€ºçã§ãããæ¡ä»¶ãã§ãã¯ãå¿ èŠã§ãã
`using`ã䜿çšããå ŽåïŒåæïŒïŒ
ã¢ãã¯ã®`FileHandle`ãç Žæ£å¯èœã«ããããã«ããããæ¡åŒµããŸãïŒ
// Redefine mock functions for clarity with Disposable
const disposableMockFiles = {};
class DisposableFileHandle {
constructor(path, mode) {
this.path = path;
this.mode = mode;
this.isOpen = true;
this.content = (path === 'errorFile.txt') ? 'This file contains an error string.' : 'Some important data.';
disposableMockFiles[path] = this;
console.log(`DisposableFileHandle '${this.path}' opened.`);
}
read() {
if (!this.isOpen) throw new Error(`File handle '${this.path}' is closed.`);
console.log(`Reading from DisposableFileHandle '${this.path}'.`);
return this.content;
}
[Symbol.dispose]() {
if (this.isOpen) {
this.isOpen = false;
delete disposableMockFiles[this.path];
console.log(`DisposableFileHandle '${this.path}' disposed via Symbol.dispose.`);
}
}
}
function processFileUsing(filePath) {
using file = new DisposableFileHandle(filePath, 'r'); // Automatically disposes 'file'
const content = file.read();
console.log(`Processing content from '${filePath}': ${content.substring(0, 20)}...`);
if (content.includes('error')) {
throw new Error(`Detected problematic content in '${filePath}'.`);
}
return content.length;
}
console.log('--- Demonstrating using statement cleanup ---');
try {
processFileUsing('safe.txt');
processFileUsing('errorFile.txt'); // This will throw
} catch (e) {
console.error(`Error caught outside: ${e.message}`);
}
console.log('--- End using statement ---');
`using`ããŒãžã§ã³ã¯ãã€ã©ãŒãã¬ãŒããå€§å¹ ã«åæžããŸããæç€ºçãª`try...finally`ã`if (file)`ã®ãã§ãã¯ã¯ããå¿ èŠãããŸããã`using file = ...`ãšãã宣èšã¯ã`processFileUsing`颿°ã®ã¹ã³ãŒããçµäºããéã«ããããæ£åžžã«å®äºãããäŸå€çµç±ã§ãããã«é¢ããããèªåçã«`[Symbol.dispose]()`ãåŒã³åºããã€ã³ãã£ã³ã°ã確ç«ããŸããããã«ãããã³ãŒãã¯ããã¯ãªãŒã³ã§èªã¿ããããæ¬è³ªçã«ãããªãœãŒã¹ãªãŒã¯ã«å¯ŸããŠå ç¢ã«ãªããŸãã
ãã¹ãããã`using`æãšç Žæ£ã®é åº
`try...finally`ãšåæ§ã«ã`using`æããã¹ãã§ããŸããã¯ãªãŒã³ã¢ããã®é åºã¯éèŠã§ãããªãœãŒã¹ã¯ååŸãããé åºãšã¯éã®é åºã§ç Žæ£ãããŸãããã®ãåŸå ¥ãå åºããïŒLIFOïŒååã¯çŽæçã§ããããªãœãŒã¹ç®¡çã«ãããŠäžè¬çã«æ£ãããå€åŽã®ãªãœãŒã¹ããããã«äŸåããå¯èœæ§ã®ããå åŽã®ãªãœãŒã¹ã®åŸã«ã¯ãªãŒã³ã¢ãããããããšãä¿èšŒããŸãã
class NestedResource {
constructor(id) {
this.id = id;
console.log(`Resource ${this.id} acquired.`);
}
[Symbol.dispose]() {
console.log(`Resource ${this.id} disposed.`);
}
performAction() {
console.log(`Resource ${this.id} performing action.`);
if (this.id === 'inner' && Math.random() < 0.3) {
throw new Error(`Error in inner resource ${this.id}`);
}
}
}
function manageNestedResources() {
console.log('--- Entering manageNestedResources ---');
using outer = new NestedResource('outer');
outer.performAction();
try {
using inner = new NestedResource('inner');
inner.performAction();
console.log('Both inner and outer resources completed successfully.');
} catch (e) {
console.error(`Caught exception in inner block: ${e.message}`);
} // inner is disposed here, before outer block continues or exits
outer.performAction(); // Outer resource is still active here if no error
console.log('--- Exiting manageNestedResources ---');
} // outer is disposed here
manageNestedResources();
console.log('---');
manageNestedResources(); // Run again to potentially hit the error case
ãã®äŸã§ã¯ãå åŽã®`using`ãããã¯å ã§ãšã©ãŒãçºçããå ŽåããŸã`inner`ãç Žæ£ãããæ¬¡ã«`catch`ãããã¯ããšã©ãŒãåŠçããæçµçã«`manageNestedResources`ãçµäºããéã«`outer`ãç Žæ£ãããŸãããã®äºæž¬å¯èœã§ä¿èšŒãããé åºã¯ãå ç¢ãªãªãœãŒã¹ç®¡çã®ç€ç³ã§ãã
`await using`ã«ããéåæãªãœãŒã¹
çŸä»£ã®JavaScriptã¢ããªã±ãŒã·ã§ã³ã¯ãéåžžã«éåæã§ããéåæã¯ãªãŒã³ã¢ãããå¿ èŠãšãããªãœãŒã¹ïŒäŸïŒPromiseãè¿ããããã¯ãŒã¯æ¥ç¶ã®ã¯ããŒãºãéåæI/Oæäœã䌎ãããŒã¿ããŒã¹ãã©ã³ã¶ã¯ã·ã§ã³ã®ã³ãããïŒã®ç®¡çã¯ãããèªèº«ã®èª²é¡ãæç€ºããŸãã`using`æã¯ã`await using`ã§ããã«å¯ŸåŠããŸãã
`await using`ãš`Symbol.asyncDispose`ã®å¿ èŠæ§
`await`ã`Promise`ãšå ±ã«äœ¿çšãããéåææäœãå®äºãããŸã§å®è¡ãäžæåæ¢ããããã«ã`await using`ã¯`Symbol.asyncDispose`ãå®è£ ãããªããžã§ã¯ããšå ±ã«äœ¿çšãããŸããããã«ãããå²ãã¹ã³ãŒããå®å šã«çµäºããåã«ãéåæã¯ãªãŒã³ã¢ããæäœãå®äºããããšãä¿èšŒãããŸãã`await`ããªãå Žåãã¯ãªãŒã³ã¢ããæäœã¯éå§ããããã®ã®å®äºããªãå¯èœæ§ãããããã®çµæããªãœãŒã¹ãªãŒã¯ããåŸç¶ã®ã³ãŒãããŸã ç Žæ£äžã®ãªãœãŒã¹ã䜿çšããããšããç«¶åç¶æ ã«ã€ãªããå¯èœæ§ããããŸãã
`AsyncNetworkConnection`ãªãœãŒã¹ãå®çŸ©ããŸãããïŒ
class AsyncNetworkConnection {
constructor(url) {
this.url = url;
this.isConnected = false;
console.log(`Attempting to connect to ${this.url}...`);
// Simulate async connection establishment
this.connectPromise = new Promise(resolve => setTimeout(() => {
this.isConnected = true;
console.log(`Connected to ${this.url}.`);
resolve();
}, 50));
}
async ensureConnected() {
await this.connectPromise;
}
async sendData(data) {
await this.ensureConnected();
console.log(`Sending '${data}' over ${this.url}.`);
await new Promise(resolve => setTimeout(resolve, 30)); // Simulate network latency
if (data.includes('critical_error')) {
throw new Error(`Network error sending '${data}'.`);
}
return `Data '${data}' sent successfully.`
}
async [Symbol.asyncDispose]() {
if (this.isConnected) {
console.log(`Disconnecting from ${this.url} asynchronously...`);
await new Promise(resolve => setTimeout(resolve, 100)); // Simulate async disconnect
this.isConnected = false;
console.log(`Disconnected from ${this.url}.`);
} else {
console.log(`Connection to ${this.url} was already closed or failed to connect.`);
}
}
}
async function handleNetworkRequest(targetUrl, payload) {
console.log(`--- Handling request for ${targetUrl} ---`);
// 'await using' ensures the connection is closed asynchronously
await using connection = new AsyncNetworkConnection(targetUrl);
await connection.ensureConnected(); // Ensure connection is ready before sending
try {
const response = await connection.sendData(payload);
console.log(`Response: ${response}`);
} catch (e) {
console.error(`Caught error during sendData: ${e.message}`);
// Even if an error occurs here, 'connection' will still be asynchronously disposed
}
console.log(`--- Finished handling request for ${targetUrl} ---`);
} // 'connection' is asynchronously disposed here
async function runAsyncExamples() {
await handleNetworkRequest('api.example.com/data', 'hello_world');
console.log('\n--- Next request ---\n');
await handleNetworkRequest('api.example.com/critical', 'critical_error_data'); // This will throw
console.log('\n--- All requests processed ---\n');
}
runAsyncExamples().catch(err => console.error(`Top-level async error: ${err.message}`));
`handleNetworkRequest`ã§ã¯ã`await using connection = ...`ã«ããã颿°ãçµäºãããšãã«`connection[Symbol.asyncDispose]()`ãåŒã³åºãããåŸ æ©ãããããšãä¿èšŒãããŸãããã`sendData`ããšã©ãŒãã¹ããŒããŠãã`catch`ãããã¯ãå®è¡ãããŸããã`connection`ã®éåæç Žæ£ã¯äŸç¶ãšããŠä¿èšŒãããéãããŸãŸã®ãããã¯ãŒã¯ãœã±ãããæ®ãã®ãé²ããŸããããã¯éåææäœã®ä¿¡é Œæ§ã«ãšã£ãŠç»æçãªæ¹åã§ãã
ç°¡æœããè¶ ãã`using`ã®åºç¯å²ã«ãããå©ç¹
`using`æã¯ééããªãããç°¡æœãªæ§æãæäŸããŸããããã®çã®äŸ¡å€ã¯ãã³ãŒãã®å質ãä¿å®æ§ãããã³ã¢ããªã±ãŒã·ã§ã³å šäœã®å ç¢æ§ã«åœ±é¿ãäžããã¯ããã«åºç¯å²ã«åã³ãŸãã
å¯èªæ§ãšä¿å®æ§ã®åäž
ã³ãŒãã®æç¢ºãã¯ãä¿å®å¯èœãªãœãããŠã§ã¢ã®åºç€ã§ãã`using`æã¯ããªãœãŒã¹ç®¡çã®æå³ãæç¢ºã«ç€ºããŸããéçºè ã`using`ãèŠããšã宣èšããã倿°ãèªåçã«ã¯ãªãŒã³ã¢ããããããªãœãŒã¹ã衚ãããšãå³åº§ã«çè§£ããŸããããã«ãããèªç¥è² è·ã軜æžãããå¶åŸ¡ãããŒã远跡ãããªãœãŒã¹ã®ã©ã€ããµã€ã¯ã«ã«ã€ããŠæšè«ããããšã容æã«ãªããŸãã
- èªå·±ææžåã³ãŒãïŒããŒã¯ãŒã`using`èªäœããªãœãŒã¹ç®¡çã®æç¢ºãªææšãšããŠæ©èœãã`try...finally`ãããã¯ã®åšãã«åºç¯ãªã³ã¡ã³ããèšè¿°ããå¿ èŠããªããªããŸãã
- èŠèŠçãªç ©éãã®è»œæžïŒåé·ãª`finally`ãããã¯ãåé€ããããšã§ã颿°å ã®äž»èŠãªããžãã¹ããžãã¯ãããéç«ã¡ãèªã¿ããããªããŸãã
- ã³ãŒãã¬ãã¥ãŒã®å®¹æåïŒã³ãŒãã¬ãã¥ãŒäžããªãœãŒã¹ãé©åã«åŠçãããŠãããã確èªããã®ãç°¡åã«ãªããŸããè²¬ä»»ã¯æåãã§ãã¯ã§ã¯ãªãã`using`æã«å§ããããããã§ãã
ãã€ã©ãŒãã¬ãŒãã®åæžãšéçºè çç£æ§ã®åäž
ãã€ã©ãŒãã¬ãŒãã³ãŒãã¯å埩çã§ãç¬èªã®äŸ¡å€ã远å ããããã°ã®çºçé åãå¢ãããŸãã`try...finally`ãã¿ãŒã³ã¯ãç¹ã«è€æ°ã®ãªãœãŒã¹ãéåææäœãæ±ãå Žåã«ããã°ãã°ããªãã®ãã€ã©ãŒãã¬ãŒãã«ã€ãªãããŸãã
- ã³ãŒãè¡æ°ã®åæžïŒæžããèªãããããã°ããã³ãŒããå°ãªããªãããšã«çŽæ¥ã€ãªãããŸãã
- æšæºåãããã¢ãããŒãïŒã³ãŒãããŒã¹å šäœã§ãªãœãŒã¹ã管çããäžè²«ããæ¹æ³ãä¿é²ããæ°ããããŒã ã¡ã³ããŒãæ¢åã®ã³ãŒãã«æ £ããçè§£ãããããªããŸãã
- ããžãã¹ããžãã¯ãžã®éäžïŒéçºè ã¯ããªãœãŒã¹ç Žæ£ã®ã¡ã«ããºã ã§ã¯ãªããã¢ããªã±ãŒã·ã§ã³ã®ç¬èªã®ããžãã¯ã«éäžã§ããŸãã
ä¿¡é Œæ§ã®åäžãšãªãœãŒã¹ãªãŒã¯ã®é²æ¢
ãªãœãŒã¹ãªãŒã¯ã¯ãæéã®çµéãšãšãã«ã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ãåŸã ã«äœäžãããæçµçã«ã¯ã©ãã·ã¥ãã·ã¹ãã äžå®å®æ§ã«ã€ãªããåä»ãªãã°ã§ãããã®çç¶ãé·æéã®æäœåŸãç¹å®ã®è² è·æ¡ä»¶äžã§ã®ã¿çŸããããšãããããããããã°ãç¹ã«å°é£ã§ãã
- ä¿èšŒãããã¯ãªãŒã³ã¢ããïŒããã¯ééããªãæãéèŠãªå©ç¹ã§ãã`using`ã¯ãæªåŠçã®äŸå€ã`return`æããŸãã¯åŸæ¥ã®ã¯ãªãŒã³ã¢ããããžãã¯ããã€ãã¹ãã`break`/`continue`æãååšããå Žåã§ãã`Symbol.dispose`ãŸãã¯`Symbol.asyncDispose`ãåžžã«åŒã³åºãããããšãä¿èšŒããŸãã
- äºæž¬å¯èœãªåäœïŒäºæž¬å¯èœã§äžè²«ããã¯ãªãŒã³ã¢ããã¢ãã«ãæäŸããããã¯é·æéå®è¡ããããµãŒãã¹ãããã·ã§ã³ã¯ãªãã£ã«ã«ãªã¢ããªã±ãŒã·ã§ã³ã«ãšã£ãŠäžå¯æ¬ ã§ãã
- éçšãªãŒããŒãããã®åæžïŒãªãœãŒã¹ãªãŒã¯ãå°ãªããšããããšã¯ãããå®å®ããã¢ããªã±ãŒã·ã§ã³ãæå³ããé »ç¹ãªåèµ·åãæåä»å ¥ã®å¿ èŠæ§ãæžãããŸããããã¯ãã°ããŒãã«ã«å±éããããµãŒãã¹ã«ãšã£ãŠç¹ã«æçã§ãã
匷åãããäŸå€å®å šæ§ãšå ç¢ãªãšã©ãŒåŠç
äŸå€å®å šæ§ãšã¯ãäŸå€ãã¹ããŒããããšãã«ããã°ã©ã ãã©ãã ãããŸãåäœããããæããŸãã`using`æã¯ãJavaScriptã³ãŒãã®äŸå€å®å šãããã¡ã€ã«ãå€§å¹ ã«åäžãããŸãã
- ãšã©ãŒã®å°ã蟌ãïŒãªãœãŒã¹äœ¿çšäžã«ãšã©ãŒãã¹ããŒãããŠãããªãœãŒã¹èªäœã¯ã¯ãªãŒã³ã¢ãããããããããšã©ãŒãåæã«ãªãœãŒã¹ãªãŒã¯ãåŒãèµ·ããããšãé²ããŸããããã«ãããåäžã®é害ç¹ãè€æ°ã®ç¡é¢ä¿ãªåé¡ã«é£éããããšããªããªããŸãã
- ãšã©ãŒå埩ã®ç°¡çŽ åïŒéçºè ã¯ãäž»èŠãªãšã©ãŒïŒäŸïŒãããã¯ãŒã¯é害ïŒã®åŠçã«éäžã§ããé¢é£ããæ¥ç¶ãé©åã«éãããããã©ãããåæã«å¿é ããå¿ èŠããããŸããã`using`æããã®é¢åãèŠãŸãã
- 決å®è«çãªã¯ãªãŒã³ã¢ããé åºïŒãã¹ãããã`using`æã®å ŽåãLIFOã®ç Žæ£é åºã«ãããäŸåé¢ä¿ãæ£ããåŠçãããããšãä¿èšŒãããå ç¢ãªãšã©ãŒå埩ã«ããã«è²¢ç®ããŸãã
`using`ã®å®è·µçãªèæ ®äºé ãšãã¹ããã©ã¯ãã£ã¹
`using`æã广çã«æŽ»çšããã«ã¯ãéçºè ã¯ç Žæ£å¯èœãªãªãœãŒã¹ãå®è£ ããæ¹æ³ãšããã®æ©èœãéçºã¯ãŒã¯ãããŒã«çµ±åããæ¹æ³ãçè§£ããå¿ èŠããããŸãã
ç¬èªã®ç Žæ£å¯èœãªãœãŒã¹ãå®è£ ãã
`using`ã®çã®åã¯ãå€éšãªãœãŒã¹ã管çããç¬èªã®ã¯ã©ã¹ãäœæãããšãã«çºæ®ãããŸããåæããã³éåæã®ç Žæ£å¯èœãªããžã§ã¯ãã®ãã³ãã¬ãŒãã以äžã«ç€ºããŸãïŒ
// Example: A hypothetical database transaction manager
class DbTransaction {
constructor(dbConnection) {
this.db = dbConnection;
this.isActive = false;
console.log('DbTransaction: Initializing...');
}
async begin() {
console.log('DbTransaction: Beginning transaction...');
// Simulate async DB operation
await new Promise(resolve => setTimeout(resolve, 50));
this.isActive = true;
console.log('DbTransaction: Transaction active.');
}
async commit() {
if (!this.isActive) throw new Error('Transaction not active.');
console.log('DbTransaction: Committing transaction...');
await new Promise(resolve => setTimeout(resolve, 100)); // Simulate async commit
this.isActive = false;
console.log('DbTransaction: Transaction committed.');
}
async rollback() {
if (!this.isActive) return; // Nothing to roll back if not active
console.log('DbTransaction: Rolling back transaction...');
await new Promise(resolve => setTimeout(resolve, 80)); // Simulate async rollback
this.isActive = false;
console.log('DbTransaction: Transaction rolled back.');
}
async [Symbol.asyncDispose]() {
if (this.isActive) {
// If the transaction is still active when scope exits, it means it wasn't committed.
// We should roll it back to prevent inconsistencies.
console.warn('DbTransaction: Transaction not explicitly committed, rolling back during disposal.');
await this.rollback();
}
console.log('DbTransaction: Resource cleanup complete.');
}
}
// Example usage
async function performDatabaseOperation(dbConnection, shouldError) {
console.log('\n--- Starting database operation ---');
await using tx = new DbTransaction(dbConnection); // tx will be disposed
await tx.begin();
try {
// Perform some database writes/reads
console.log('DbTransaction: Performing data operations...');
await new Promise(resolve => setTimeout(resolve, 70));
if (shouldError) {
throw new Error('Simulated database write error.');
}
await tx.commit();
console.log('DbTransaction: Operation successful, transaction committed.');
} catch (e) {
console.error(`DbTransaction: Error during operation: ${e.message}`);
// Rollback is implicitly handled by [Symbol.asyncDispose] if commit wasn't reached,
// but explicit rollback here can also be used if preferred for immediate feedback
// await tx.rollback();
throw e; // Re-throw to propagate the error
}
console.log('--- Database operation finished ---');
}
// Mock DB connection
const mockDb = {};
async function runDbExamples() {
await performDatabaseOperation(mockDb, false);
await performDatabaseOperation(mockDb, true).catch(err => {
console.error(`Top-level caught DB error: ${err.message}`);
});
}
runDbExamples();
ãã®`DbTransaction`ã®äŸã§ã¯ã`[Symbol.asyncDispose]`ãæŠç¥çã«äœ¿çšããã`using`ã¹ã³ãŒããçµäºããåã«éå§ããããæç€ºçã«ã³ããããããªãã£ããã¹ãŠã®ãã©ã³ã¶ã¯ã·ã§ã³ãèªåçã«ããŒã«ããã¯ããŸããããã¯ãããŒã¿æŽåæ§ãšäžè²«æ§ãä¿èšŒããããã®åŒ·åãªãã¿ãŒã³ã§ãã
`using`ã䜿çšãã¹ãæïŒãšããã§ãªãæïŒ
`using`æã¯åŒ·åãªããŒã«ã§ãããä»ã®ããŒã«ãšåæ§ã«æé©ãªäœ¿çšã±ãŒã¹ããããŸãã
- `using`ã䜿çšãã¹ãæïŒ
- ã·ã¹ãã ãªãœãŒã¹ïŒãã¡ã€ã«ãã³ãã«ããããã¯ãŒã¯ãœã±ãããããŒã¿ããŒã¹æ¥ç¶ãããã¯ãªã©ïŒãã«ãã»ã«åãããªããžã§ã¯ãã
- ãªã»ãããŸãã¯ã¯ãªãŒã³ã¢ãããå¿ èŠãªç¹å®ã®ç¶æ ãç¶æãããªããžã§ã¯ãïŒäŸïŒãã©ã³ã¶ã¯ã·ã§ã³ãããŒãžã£ãŒãäžæçãªã³ã³ããã¹ãïŒã
- `close()`ã`dispose()`ã`release()`ããŸãã¯`rollback()`ã¡ãœããã®åŒã³åºããå¿ãããšåé¡ãçºçãããããããªãœãŒã¹ã
- äŸå€å®å šæ§ãæãéèŠãªæžå¿µäºé ã§ããã³ãŒãã
- `using`ãé¿ããã¹ãæïŒ
- å€éšãªãœãŒã¹ã管çããªãããŸãã¯ç¹å¥ãªã¯ãªãŒã³ã¢ãããå¿ èŠãšããç¶æ ãä¿æããªãåçŽãªããŒã¿ãªããžã§ã¯ãïŒäŸïŒãã¬ãŒã³ãªé åããªããžã§ã¯ããæååãæ°å€ïŒã
- ã©ã€ããµã€ã¯ã«ãã¬ããŒãžã³ã¬ã¯ã¿ãŒã«ãã£ãŠå®å šã«ç®¡çãããŠãããªããžã§ã¯ãïŒäŸïŒã»ãšãã©ã®æšæºJavaScriptãªããžã§ã¯ãïŒã
- ããªãœãŒã¹ããã°ããŒãã«èšå®ããããŒã«ã«ã¹ã³ãŒãã«çµã³ã€ããã¹ãã§ã¯ãªãã¢ããªã±ãŒã·ã§ã³å šäœã®ã©ã€ããµã€ã¯ã«ãæã€ãã®ã§ããå Žåã
åŸæ¹äºææ§ãšããŒã«ã³ã°ã«é¢ããèæ ®äºé
2024幎åé çŸåšã`using`æã¯JavaScriptèšèªã«æ¯èŒçæ°ãã远å ããããã®ã§ãTC39ããããŒã¶ã«æ®µéïŒçŸåšã¹ããŒãž3ïŒãé²ãã§ããŸããããã¯ããããååã«ä»æ§åãããŠããäžæ¹ã§ããã¹ãŠã®çŸåšã®ã©ã³ã¿ã€ã ç°å¢ïŒãã©ãŠã¶ãNode.jsããŒãžã§ã³ïŒã§ãã€ãã£ãã«ãµããŒããããŠããªãå¯èœæ§ãããããšãæå³ããŸãã
- ãã©ã³ã¹ãã€ã«ïŒæ¬çªç°å¢ã§ããã«äœ¿çšããã«ã¯ãéçºè ã¯Babelã®ãããªãã©ã³ã¹ãã€ã©ããé©åãªããªã»ããïŒ`@babel/preset-env`ã`bugfixes`ãš`shippedProposals`ãæå¹ã«ããŠããŸãã¯ç¹å®ã®ãã©ã°ã€ã³ïŒã§èšå®ããŠäœ¿çšããå¿ èŠãããã§ãããããã©ã³ã¹ãã€ã©ã¯æ°ãã`using`æ§æãåçã®`try...finally`ãã€ã©ãŒãã¬ãŒãã«å€æãã仿¥ããã¢ãã³ãªã³ãŒããæžãããšãå¯èœã«ããŸãã
- ã©ã³ã¿ã€ã ãµããŒãïŒã¿ãŒã²ãããšããJavaScriptã©ã³ã¿ã€ã ïŒNode.jsããã©ãŠã¶ããŒãžã§ã³ïŒã®ãªãªãŒã¹ããŒãã«æ³šç®ãããã€ãã£ããµããŒãã確èªããŠãã ãããæ®åãé²ãã«ã€ããŠããã€ãã£ããµããŒãã¯åºç¯å²ã«åã¶ã§ãããã
- TypeScriptïŒTypeScriptã`using`ããã³`await using`æ§æããµããŒãããŠãããç Žæ£å¯èœãªãœãŒã¹ã®åå®å šæ§ãæäŸããŸãã`tsconfig.json`ãååã«ã¢ãã³ãªECMAScriptããŒãžã§ã³ãã¿ãŒã²ãããšããå¿ èŠãªã©ã€ãã©ãªåãå«ãã§ããããšã確èªããŠãã ããã
ç Žæ£äžã®ãšã©ãŒéçŽïŒãã¥ã¢ã³ã¹ïŒ
`using`æãç¹ã«`await using`ã®æŽç·ŽãããåŽé¢ã¯ãç Žæ£ããã»ã¹ãã®ãã®ã§çºçããå¯èœæ§ã®ãããšã©ãŒãã©ã®ããã«åŠçããããšããç¹ã§ãã`using`ãããã¯å ã§äŸå€ãçºçãããã®åŸã`[Symbol.dispose]`ãŸãã¯`[Symbol.asyncDispose]`ã¡ãœããå ã§å¥ã®äŸå€ãçºçããå ŽåãJavaScriptã®ä»æ§ã§ã¯ããšã©ãŒéçŽãã®ããã®ã¡ã«ããºã ãèŠå®ãããŠããŸãã
äž»ãªäŸå€ïŒ`using`ãããã¯ããã®ãã®ïŒã¯éåžžåªå ãããŸãããç Žæ£ã¡ãœããããã®äŸå€ã¯å€±ãããŸãããå€ãã®å Žåãå ã®äŸå€ãäŒæããããšã蚱容ãã€ã€ãç Žæ£äŸå€ãèšé²ãããïŒäŸïŒãµããŒããããŠããç°å¢ã§ã¯`SuppressedError`ãšããŠããŸãã¯ãã°ã«èšé²ãããïŒãããªæ¹æ³ã§ãæå¶ããããŸããããã«ãããåŒã³åºãå ã³ãŒããéåžžç®ã«ããã®ã¯å ã®é害åå ã§ããããšãä¿èšŒãããã¯ãªãŒã³ã¢ããäžã®äºæ¬¡çãªé害ãèªèãããŸããéçºè ã¯ãã®ããšãèªèãã`[Symbol.dispose]`ããã³`[Symbol.asyncDispose]`ã¡ãœãããå¯èœãªéãå ç¢ã§ãã©ãŒã«ããã¬ã©ã³ãã«èšèšãã¹ãã§ããçæ³çã«ã¯ãç Žæ£ã¡ãœããèªäœã¯ãã¯ãªãŒã³ã¢ããäžã«æ¬åœã«å埩äžèœãªãšã©ãŒãçºçããããããããªãè«ççç Žæãé²ãããã«å¿ ã衚é¢åãããå¿ èŠãããå Žåãé€ããäŸå€ãã¹ããŒãã¹ãã§ã¯ãããŸããã
çŸä»£JavaScriptéçºã«ãããã°ããŒãã«ãªåœ±é¿ãšæ¡çš
- ãšã³ã·ã¹ãã å šäœã§ã®æšæºåïŒãªãœãŒã¹ç®¡çã®ããã®æšæºåãããèšèªã¬ãã«ã®æ§é ãæäŸããããšã§ãJavaScriptã¯ä»ã®å ç¢ãªããã°ã©ãã³ã°èšèªã§ç¢ºç«ããããã¹ããã©ã¯ãã£ã¹ãšãã坿¥ã«é£æºããŸããããã«ãããèšèªéãç§»è¡ããéçºè ã«ãšã£ãŠãã容æã«ãªããä¿¡é Œæ§ã®é«ããªãœãŒã¹åŠçã«é¢ããå ±éçè§£ãä¿é²ããŸãã
- ããã¯ãšã³ããµãŒãã¹ã®æ¹åïŒãã¡ã€ã«ã·ã¹ãã ãããŒã¿ããŒã¹ããããã¯ãŒã¯ãªãœãŒã¹ãšã®ããåããçµ¶ãéãªããµãŒããŒãµã€ãJavaScriptïŒNode.jsïŒã§ã¯ã`using`ã¯äžçäžã§äœ¿çšãããé·æé皌åãµãŒãã¹ããã€ã¯ããµãŒãã¹ãAPIã®å®å®æ§ãšããã©ãŒãã³ã¹ãåçã«åäžãããã§ãããããããã®ç°å¢ã§ã®ãªãŒã¯é²æ¢ã¯ãã¹ã±ãŒã©ããªãã£ãšçšŒåæéã«ãšã£ãŠäžå¯æ¬ ã§ãã
- ããå ç¢ãªããã³ããšã³ãã¢ããªã±ãŒã·ã§ã³ïŒããŸãäžè¬çã§ã¯ãããŸããããããã³ããšã³ãã¢ããªã±ãŒã·ã§ã³ããªãœãŒã¹ïŒWeb WorkerãIndexedDBãã©ã³ã¶ã¯ã·ã§ã³ãWebGLã³ã³ããã¹ããç¹å®ã®UIèŠçŽ ã®ã©ã€ããµã€ã¯ã«ïŒã管çããŸãã`using`ã¯ãè€éãªç¶æ ãšã¯ãªãŒã³ã¢ãããé©åã«åŠçãããããå ç¢ãªã·ã³ã°ã«ããŒãžã¢ããªã±ãŒã·ã§ã³ãå¯èœã«ããã°ããŒãã«ã«ãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãåäžãããŸãã
- ããŒã«ãšã©ã€ãã©ãªã®åŒ·åïŒ`Disposable`ããã³`AsyncDisposable`ãããã³ã«ã®ååšã¯ãã©ã€ãã©ãªäœæè ã`using`ãšäºææ§ã®ããAPIãèšèšããããšã奚å±ããŸããããã«ãããããå€ãã®ã©ã€ãã©ãªãæ¬è³ªçã«èªåçã§ä¿¡é Œæ§ã®é«ãã¯ãªãŒã³ã¢ãããæäŸãããã¹ãŠã®ããŠã³ã¹ããªãŒã ã³ã³ã·ã¥ãŒããŒã«å©çããããããŸãã
- æè²ãšãã¹ããã©ã¯ãã£ã¹ïŒ`using`æã¯ãæ°ããéçºè ã«ãšã£ãŠãªãœãŒã¹ç®¡çãšäŸå€å®å šæ§ã®éèŠæ§ã«ã€ããŠæç¢ºãªæèšãæäŸããæåããããå ç¢ãªã³ãŒããæžãæåãè²ã¿ãŸãã
- çžäºéçšæ§ïŒJavaScriptãšã³ãžã³ãæçãããã®æ©èœãæ¡çšããã«ã€ããŠãã³ãŒãããã©ãŠã¶ããµãŒããŒããŸãã¯çµã¿èŸŒã¿ç°å¢ã®ã©ãã§å®è¡ããããã«é¢ããããäžè²«ãããªãœãŒã¹åäœãä¿èšŒããã¯ãã¹ãã©ãããã©ãŒã ã¢ããªã±ãŒã·ã§ã³ã®éçºãå¹çåããŸãã
JavaScriptãå°åIoTããã€ã¹ããå€§èŠæš¡ãªã¯ã©ãŠãã€ã³ãã©ã¹ãã©ã¯ãã£ãŸã§ãããããã®ãåããäžçã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã®ä¿¡é Œæ§ãšãªãœãŒã¹å¹çãæéèŠã§ãã`using`æã¯ããããã®ã°ããŒãã«ãªããŒãºã«çŽæ¥å¯ŸåŠããéçºè ãããå®å®ããäºæž¬å¯èœã§ã髿§èœãªãœãããŠã§ã¢ãæ§ç¯ã§ããããã«ããŸãã
çµè«ïŒããä¿¡é Œæ§ã®é«ãJavaScriptã®æªæ¥ãåãå ¥ãã
`using`æã¯ã`Symbol.dispose`ããã³`Symbol.asyncDispose`ãããã³ã«ãšãšãã«ãJavaScriptèšèªã«ãããéèŠãã€æè¿ãã¹ã鲿©ãæå³ããŸããããã¯ãå ç¢ã§ä¿å®å¯èœãªãœãããŠã§ã¢ã·ã¹ãã ãæ§ç¯ããäžã§äžå¯æ¬ ãªåŽé¢ã§ãããäŸå€å®å šãªãªãœãŒã¹ç®¡çãšããé·å¹Žã®èª²é¡ã«çŽæ¥åãçµã¿ãŸãã
ãªãœãŒã¹ã¯ãªãŒã³ã¢ããã®ããã®å®£èšçã§ç°¡æœãã€ä¿èšŒãããã¡ã«ããºã ãæäŸããããšã§ã`using`ã¯éçºè ããæåã®`try...finally`ãããã¯ã®å埩çã§ãšã©ãŒãçºçãããããã€ã©ãŒãã¬ãŒãããè§£æŸããŸãããã®å©ç¹ã¯åãªãã·ã³ã¿ãã¯ã¹ã·ã¥ã¬ãŒã«ãšã©ãŸãããã³ãŒãã®å¯èªæ§ã®åäžãéçºåŽåã®åæžãä¿¡é Œæ§ã®åŒ·åããããŠæãéèŠãªããšãšããŠãäºæãã¬ãšã©ãŒã«çŽé¢ããå Žåã§ããªãœãŒã¹ãªãŒã¯ã«å¯Ÿããå ç¢ãªä¿èšŒãå«ã¿ãŸãã
JavaScriptãæçãç¶ããäžçäžã§ãŸããŸãåºç¯å²ã®ã¢ããªã±ãŒã·ã§ã³ãåããããã«ãªãã«ã€ããŠã`using`ã®ãããªæ©èœã¯äžå¯æ¬ ã§ãããããã¯ãéçºè ãçŸä»£ã®ãœãããŠã§ã¢èŠä»¶ã®è€éãã«èããããããã¯ãªãŒã³ã§å埩åã®ããã³ãŒããæžãããšãå¯èœã«ããŸããçŸåšã®ãããžã§ã¯ãã®èŠæš¡ãé åã«é¢ãããããã¹ãŠã®JavaScriptéçºè ããã®åŒ·åãªæ°æ©èœãæ¢æ±ãããã®æå³åããçè§£ããç Žæ£å¯èœãªãœãŒã¹ãèªèº«ã®ã¢ãŒããã¯ãã£ã«çµ±åãå§ããããšã奚å±ããŸãã`using`æãåãå ¥ããJavaScriptã¢ããªã±ãŒã·ã§ã³ã®ããä¿¡é Œæ§ãé«ããäŸå€å®å šãªæªæ¥ãæ§ç¯ããŸãããã