以下是一些 GNOME 扩展的简单场景:
- 启用扩展。扩展是一个扩展的类
Clutter.Actor
. - 它创建了一个名为
myActor
的 actor 并添加了它:this.add_child(myActor)
. - 然后它调用一个异步的
耗时的函数
this._tcFunction()
最后做了一些事情 使用myActor
。
这是我遇到的问题:
我们在启用扩展后立即禁用(运行
this.destroy()
)。禁用时,
this.destroy()
运行 GObject 的this.run_dispose()
以 收集垃圾。但是,如果this._tcFunction()
还没有运行完, 稍后它会尝试访问可能已经存在的myActor
由this.run_dispose()
释放。
解决此问题的一种方法是在 this.destroy()
destroy() {
this._destroying = true
// ...
this.run_dispose;
}
然后在this._tcFunction()
中添加一个检查,例如
async _tcFunction() {
await this._timeConsumingStuff();
if (this._destroying === true) { return; }
myActor.show();
}
我的问题:是否有更好的方法来处理这些情况?也许使用 Gio.Cancellable()
? AFAIK,没有简单的方法来停止 javascript 中的异步函数...
最佳答案
首先要注意两点:
避免调用像
GObject.run_dispose()
这样的低级内存管理函数,因为在 C 库中有一些情况,这些对象被缓存以供重用,而不是实际上当你认为他们被处置时。也没有处置信号,其他对象可能需要通知。避免覆盖触发处理的函数,例如
Clutter.Actor.destroy()
,而是使用 destroy 信号。 GObject 信号回调始终将发射对象作为第一个参数,在销毁回调中使用that 是安全的。
我可以想到几种方法来解决这个问题,但这取决于具体情况。如果异步函数是 GNOME 库异步函数,它可能确实有一个可取消的参数:
let cancellable = new Gio.Cancellable();
let actor = new Clutter.Actor();
actor.connect('destroy', () => cancellable.cancel());
Gio.File.new_for_path('foo.txt').load_contents_async(cancellable, (file, res) => {
try {
let result = file.load_contents_finish(res);
// This shouldn't be necessary if the operation succeeds (I think)
if (!cancellable.is_cancelled())
log(actor.width);
} catch (e) {
// We know it's not safe
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
log('it was cancelled');
// Probably safe, but let's check
else if (!cancellable.is_cancelled())
log(actor.width);
}
});
// The above function will begin but not finish before the
// cancellable is triggered
actor.destroy();
当然,您始终可以使用带有 Promise 的可取消对象,或仅使用常规函数/回调模式:
new Promise((resolve, reject) => {
// Some operation
resolve();
}).then(result => {
// Check the cancellable
if (!cancellable.is_cancelled())
log(actor.width);
});
另一种选择是null
您的引用,因为您可以安全地检查它:
let actor = new Clutter.Actor();
actor.connect('destroy', () => {
actor = null;
});
if (actor !== null)
log(actor.width);
关于javascript - 使用 destroy() 和异步函数避免分配错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61401790/