DisposableStack.prototype.move()
Базовый уровень Ограниченная доступность
Эта функция не является Базовым уровнем, потому что она не работает в некоторых из наиболее широко используемых браузеров.
Метод move() экземпляров DisposableStack создаёт новый экземпляр DisposableStack, который содержит те же деструкторы, что и этот стек, а затем помечает этот стек как утилизированный, не вызывая при этом ни одного деструктора.
Синтаксис
move()
Параметры
Нет.
Возвращаемое значение
Новый экземпляр DisposableStack.
Исключения
-
ReferenceError - Выбрасывается, если стек уже утилизирован.
Описание
Основное назначение move() — обеспечить передачу ответственности за утилизацию за пределы текущей области видимости. Например, ваша функция может взять на себя владение некоторыми ресурсами и утилизировать их, если произойдёт ошибка; если всё завершится успешно, вы возвращаете эти ресурсы и передаёте владение вызывающей стороне.
При использовании move() для передачи владения вызов move() должен быть самым последним шагом в вашем потоке управления, поскольку не будет владельца между моментом, когда ваш код отказывается от владения через move(), и моментом, когда вызывающая сторона получает владение из возвращаемого значения.
let resource1;
function init() {
using disposer = new DisposableStack();
resource1 = disposer.use(getResource1());
// ...
// Drop ownership immediately before returning
return disposer.move();
}
// Pick up ownership immediately after returning
using disposer = init();
let resource1;
function init() {
using disposer = new DisposableStack();
resource1 = disposer.use(getResource1());
// ...
const newDisposer = disposer.move();
// If someone adds code in between these lines and an error occurs,
// there would be no owner to free resource1
return newDisposer;
}
using disposer = init();
Также будьте осторожны со следующим шаблоном, хотя использование «хорошего» шаблона может быть очень неудобным во многих случаях:
function init() {
using disposer = new DisposableStack();
const resource1 = disposer.use(getResource1());
// ...
return { disposer: disposer.move(), resource1 };
}
const { resource1, ...rest } = init();
// If someone adds code in between these lines and an error occurs,
// there would be no owner to free resource1
using disposer = rest.disposer;
move() также можно использовать для условной утилизации в случаях, когда вы иногда можете вообще не захотеть утилизировать ресурсы. Например:
using disposer = new DisposableStack();
const server = disposer.use(makeServer());
await server.init();
if (server.ready) {
// Successfully initialized server; it now should live through the rest
// of the program. Drop its disposer and don't pick it up. It will no
// longer be disposed at all.
disposer.move();
}
// If we reach the end of the scope without running disposer.move(),
// then server isn't ready for any reason, and we dispose its resources
// by disposing the disposer.
Примеры
Захват владения стеком
function consumeStack(stack) {
using newStack = stack.move(); // newStack now owns the disposers
console.log(stack.disposed); // true
console.log(newStack.disposed); // false
// newStack is disposed here immediately before the function exits
}
const stack = new DisposableStack();
console.log(stack.disposed); // false
consumeStack(stack);
console.log(stack.disposed); // true
Разрешение утилизации ресурсов в двух ветвях кода
Основной вариант использования move() — это когда у вас есть один или несколько ресурсов, которые могут быть либо утилизированы прямо здесь, либо сохранены для последующего использования. В этом случае вы можете поместить ресурсы в DisposableStack, а затем вызвать move(), когда вам потребуется сохранить ресурсы для последующего использования.
class PluginHost {
#disposed = false;
#disposables;
#channel;
#socket;
constructor() {
// Create a DisposableStack that is disposed when the constructor exits.
// If construction succeeds, we move everything out of `disposer` and into
// `#disposables` to be disposed later.
using disposer = new DisposableStack();
// Create an IPC adapter around process.send/process.on("message").
// When disposed, it unsubscribes from process.on("message").
this.#channel = disposer.use(new NodeProcessIpcChannelAdapter(process));
// Create a pseudo-websocket that sends and receives messages over
// a NodeJS IPC channel.
this.#socket = disposer.use(new NodePluginHostIpcSocket(this.#channel));
// If we made it here, then there were no errors during construction and
// we can safely move the disposables out of `disposer` and into `#disposables`.
this.#disposables = disposer.move();
// If construction failed, then `disposer` would be disposed before reaching
// the line above. Event handlers would be removed, allowing `#channel` and
// `#socket` to be GC'd.
}
[Symbol.dispose]() {
if (this.#disposed) {
return;
}
this.#disposed = true;
// Put `this.#disposables` into a `using` variable, so it is automatically
// disposed when the function exits.
using disposables = this.#disposables;
// NOTE: we can free `#socket` and `#channel` here since they will be
// disposed by the call to `disposables[Symbol.dispose]()`, below.
// This isn't strictly a requirement for every disposable, but is
// good housekeeping since these objects will no longer be useable.
this.#socket = undefined;
this.#channel = undefined;
this.#disposables = undefined;
}
}
Спецификации
Совместимость с браузерами
| Настольные | Мобильные | Серверные | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on iOS | Samsung Internet | WebView Android | WebView on iOS | Bun | Deno | Node.js | |
move |
134 |
134 |
141 |
119 |
preview |
134 |
141 |
88 |
Нет |
29.0 |
134 |
Нет |
1.3.0 |
2.2.10 |
24.0.0 |
Смотрите также
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DisposableStack/move