[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Resource_management [Back]  [Original]

JavaScript - JavaScript | MDN

MDN Web Docs

View in English Always switch to English

JavaScript

JavaScript JavaScript JavaScript

: JavaScript FinalizationRegistry

js
const stream = new ReadableStream({
  start(controller) {
    controller.enqueue("a");
    controller.enqueue("b");
    controller.enqueue("c");
    controller.close();
  },
});

async function readUntil(stream, text) {
  const reader = stream.getReader();
  let chunk = await reader.read();

  while (!chunk.done && chunk.value !== text) {
    console.log(chunk);
    chunk = await reader.read();
  }
  // 
}

readUntil(stream, "b").then(() => {
  const anotherReader = stream.getReader();
  // TypeError: ReadableStreamDefaultReader constructor can only
  // accept readable streams that are not yet locked to a reader
});

3 "b" readUntil reader

readUntilreader.releaseLock()

  • : close()releaseLock()disconnect()

  • : reader.read() readUntil reader.releaseLock() try...finally

    js
    async function readUntil(stream, text) {
      const reader = stream.getReader();
      try {
        let chunk = await reader.read();
    
        while (!chunk.done && chunk.value !== text) {
          console.log(chunk);
          chunk = await reader.read();
        }
      } finally {
        reader.releaseLock();
      }
    }
    

  • : reader try...finally

  • : 2

    js
    const reader1 = stream1.getReader();
    const reader2 = stream2.getReader();
    try {
      // reader1  reader2 
    } finally {
      reader1.releaseLock();
      reader2.releaseLock();
    }
    

    stream2.getReader() reader1 reader1.releaseLock() reader2 try...finally

    js
    const reader1 = stream1.getReader();
    try {
      const reader2 = stream2.getReader();
      try {
        // reader1  reader2 
      } finally {
        reader2.releaseLock();
      }
    } finally {
      reader1.releaseLock();
    }
    

releaseLock JavaScript

using await using

2using await using const

js
{
  using reader1 = stream1.getReader();
  using reader2 = stream2.getReader();

  // reader1  reader2 

  // reader1  reader2 
}

using using using return/break/continue

using

using using [Symbol.dispose]() [Symbol.dispose] releaseLock

js
// 
class MyReader {
  // 
  [Symbol.dispose]() {
    this.releaseLock();
  }
  releaseLock() {
    // 
  }
}

// 
MyReader.prototype[Symbol.dispose] = MyReader.prototype.releaseLock;

using

[Symbol.dispose]() reader1 reader2 reader2 reader1 try...finally

await using using await await using [Symbol.asyncDisposable]() fileHandle.close()

js
{
  await using fileHandle = open("file.txt", "w");
  await fileHandle.write("Hello");

  // fileHandle.close() 
}

await using await await async await

[Symbol.asyncDispose]() await [Symbol.asyncDispose]()

  • using await using letconstvar
  • using await using [Symbol.dispose]() [Symbol.asyncDispose]() TypeError null undefined
  • const using await using [Symbol.dispose]()/[Symbol.asyncDispose]()
  • using

DisposableStack AsyncDisposableStack

using await using

js
let reader;
if (someCondition) {
  reader = stream.getReader();
} else {
  reader = stream.getReader({ mode: "byob" });
}

using const

js
if (someCondition) {
  using reader = stream.getReader();
} else {
  using reader = stream.getReader({ mode: "byob" });
}

if else DisposableStack

js
{
  using disposer = new DisposableStack();
  let reader;
  if (someCondition) {
    reader = disposer.use(stream.getReader());
  } else {
    reader = disposer.use(stream.getReader({ mode: "byob" }));
  }
  // 
  // 
}

using adopt()

js
{
  using disposer = new DisposableStack();
  //  [Symbol.dispose]() 
  //  using 
  //  disposer.adopt 
  const reader = disposer.adopt(stream.getReader(), (reader) =>
    reader.releaseLock(),
  );
  // 
  // 
}

defer()

js
{
  using disposer = new DisposableStack();
  disposer.defer(() => console.log(""));
  const connection1 = disposer.use(openConnection());
  const connection2 = disposer.use(openConnection());
  // connection1  connection2 
  //  connection1 
  // connection2 
}

move()

js
class MyResource {
  #resource1;
  #resource2;
  #disposables;
  constructor() {
    using disposer = new DisposableStack();
    this.#resource1 = disposer.use(getResource1());
    this.#resource2 = disposer.use(getResource2());
    // 
    //  `disposer`  `#disposables` 
    this.#disposables = disposer.move();
    // `disposer` 
    // `#resource1`  `#resource2` 
  }
  [Symbol.dispose]() {
    this.#disposables.dispose(); // `#resource2`  `#resource1` 
  }
}

AsyncDisposableStack DisposableStack use() adopt() dispose() [Symbol.asyncDispose]()

DisposableStack

using

js
async function readUntil(stream, text) {
  // `await using`  `using`  `releaseLock` 
  using reader = stream.getReader();
  let chunk = await reader.read();

  while (!chunk.done && chunk.value !== text) {
    console.log(chunk.toUpperCase());
    chunk = await reader.read();
  }
}

chunk null !chunk.done TypeError stream[Symbol.dispose]()

js
const stream = new ReadableStream({
  start(controller) {
    controller.enqueue("a");
    controller.enqueue(null);
    controller.enqueue("b");
    controller.enqueue("c");
    controller.close();
  },
});

readUntil(stream, "b")
  .catch((e) => console.error(e)) // TypeError: chunk.toUpperCase is not a function
  .then(() => {
    const anotherReader = stream.getReader();
    // 
  });

using

js
class MyReader {
  [Symbol.dispose]() {
    throw new Error("");
  }
}

function doSomething() {
  using reader = new MyReader();
  throw new Error("");
}

try {
  doSomething();
} catch (e) {
  console.error(e); // SuppressedError: An error was suppressed during disposal
}

doSomething() 21 doSomething 1 reader 2 SuppressedError 2 error suppressed

js
class MyReader {
  [Symbol.dispose]() {
    throw new Error("");
  }
}

class MyWriter {
  [Symbol.dispose]() {
    throw new Error("");
  }
}

function doSomething() {
  using reader = new MyReader();
  using writer = new MyWriter();
  throw new Error("");
}

try {
  doSomething();
} catch (e) {
  console.error(e); // SuppressedError: An error was suppressed during disposal
  console.error(e.suppressed); // SuppressedError: An error was suppressed during disposal
  console.error(e.error); // Error: 
  console.error(e.suppressed.suppressed); // Error: 
  console.error(e.suppressed.error); // Error: 
}
  • reader e.error
  • writer reader e.suppressed.error
  • e.suppressed.suppressed

URL

Blob URL Blob Blob URLURL.revokeObjectURL() URLURL url using url DisposableStack URL link.click() disposer

js
const downloadButton = document.getElementById("download-button");
const exampleBlob = new Blob(["example data"]);

downloadButton.addEventListener("click", () => {
  using disposer = new DisposableStack();
  const link = document.createElement("a");
  const url = disposer.adopt(
    URL.createObjectURL(exampleBlob),
    URL.revokeObjectURL,
  );

  link.href = url;
  link.download = "example.txt";
  link.click();
});

fetch Promise.all() Promise.all() 1 Promise.all() AbortController signal fetch() Promise.all() Promise.all()

js
async function getAllData(urls) {
  using disposer = new DisposableStack();
  const { signal } = disposer.adopt(new AbortController(), (controller) =>
    controller.abort(),
  );

  //  URL 
  // 
  const pages = await Promise.all(
    urls.map((url) =>
      fetch(url, { signal }).then((response) => {
        if (!response.ok)
          throw new Error(
            `: ${response.status} - ${response.statusText}`,
          );
        return response.text();
      }),
    ),
  );
  return pages;
}

API


Web Proxy Viewer  |  New URL  |  Original Page