javascript - 使用 destroy() 和异步函数避免分配错误
问题描述
以下是一些 GNOME 扩展的简单场景:
- 启用扩展。扩展是一个扩展类
Clutter.Actor
。 - 它创建一个名为的actor
myActor
并添加它:this.add_child(myActor)
. - 然后它调用一个异步耗时的函数
this._tcFunction()
,该函数最终对myActor
.
这是我遇到问题的地方:
this.destroy()
我们在启用后立即禁用(运行)扩展。禁用时,
this.destroy()
运行 GObjectthis.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 库中存在这样的情况:这些对象被缓存以供重用,而实际上并没有在您认为它们被释放时被释放。也没有 dispose 信号,其他对象可能需要通知。避免覆盖触发处置之类的函数,
Clutter.Actor.destroy()
而是使用销毁信号。GObject 信号回调总是将发射对象作为第一个参数,并且在销毁回调中使用它是安全的。
有几种方法我可以考虑解决这个问题,但这取决于具体情况。如果异步函数是 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);
推荐阅读
- spring - 我们如何在 where 块中使用 hashmap 作为变量
- javascript - Sails.js 项目使用 passport.js 不会重定向到 twitter 登录
- perl - 列出目录中的文件并存储在数组中。该数组可以在循环外访问
- azure-application-insights - 为 AppInsight RestAPI 上下文设置时间跨度
- java - JsonPath:按数组中任何数组中的值过滤
- javascript - 未定义导出“MyModule” - 在 Jest 测试中
- javascript - d3 v5 轴比例更改平移方式太多
- python - 尝试下载 mysqlclient 时出现 gcc 错误
- node.js - 请解释 npx 限制 - 运行 npx mocha 时无法使用断言库
- matlab - 如何使这个 for 循环每次迭代都显示一个图形?