DisposableStack.prototype.move()
move() 方法是 DisposableStack 例項的一個方法,它建立一個新的 DisposableStack 例項,該例項包含與當前堆疊相同的處置器,然後將當前堆疊標記為已處置,而不呼叫任何處置器。
語法
js
move()
引數
無。
返回值
一個新的 DisposableStack 例項。
異常
ReferenceError-
如果堆疊已被處置,則丟擲異常。
描述
move() 的主要目的是能夠將處置的責任從當前作用域轉移出去。例如,你的函式可以宣告對某些資源的所有權,並在發生錯誤時處置它們;如果一切順利完成,則返回這些資源並將所有權轉移給呼叫者。
當使用 move() 轉移所有權時,呼叫 move() 應該是你的控制流中的最後一步,因為在你透過 move() 放棄所有權和呼叫者從返回值中獲取所有權之間,將沒有中間擁有者。
js
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();
js
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();
也要注意以下模式,儘管使用“好”的模式在許多情況下可能非常笨拙
js
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() 也可以用於條件處置,在某些情況下你可能根本不想處置資源。例如:
js
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.
示例
宣告堆疊的所有權
js
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()。
js
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;
}
}
規範
| 規範 |
|---|
| ECMAScript 非同步顯式資源管理 # sec-disposablestack.prototype.move |
瀏覽器相容性
載入中…