Bluebird 承诺可以在完成之前进行 GC 吗?
Can a Bluebird promise be GC'd before completion?
假设您有以下代码:
function startApp() {
createReallyLongRunningPromise();
// intensive work with memory
}
创建的 promise 是否有任何方法可以在完成之前进行 GC,或者只要进程处于活动状态就可以保证完成工作?
如果相关,长运行 承诺的主体 returns 本身就是一个承诺:
function createReallyLongRunningPromise() {
return new Promise(resolve => {
// Stuff
return promiseCreatedDuringStuff;
});
}
Is there any way that the created promise will get GC'd before it's done or is it guaranteed to finish working as long as the process is live?
这是两个完全独立且与某人无关的问题。 :-)
如果没有任何对象引用 promise 对象,那么它自然可以被 GC 处理。 promise 实现细节将决定 resolve
函数是否可以访问 promise 对象(而不是 promise 对象也引用的更深层次的东西);如果是这样,那么对 resolve
的任何未完成引用也将保持承诺。如果没有,那么如果没有别的,对象可以被 GC。
但这与通过 promise 报告完成的异步进程无关,除了该进程可能具有对 resolve
的活动引用并因此使 resolve
函数与resolve
函数引用的任何内容。
因此,除非环境终止,否则异步过程应该完成。你没有说你在哪里做这件事,但是例如 NodeJS 在有任何未完成的计时器、I/O 请求等时保持环境活跃。
Is there any way that the created promise will get GC'd before it's
done
没有。假设异步操作仍然没有完成并且仍然有能力解决或拒绝承诺,那么它会保留对承诺对象的某种引用,因此它不能被 GC。
promise 对象只是一个普通的 Javascript 对象。它将被垃圾收集,与任何其他 Javascript 对象完全相同,即当没有活动的、可访问的代码不再引用 promise 对象时。对承诺的引用可以由正在进行的异步操作持有,也可以由异步操作的发起者和承诺的用户持有(很可能由两者共同持有)。
只要异步操作正在进行并且该异步操作的某些部分引用了承诺执行器函数的解析或拒绝回调,那么就会有一个对仍然存在的承诺对象的引用并且它根本没有资格进行垃圾收集。
一旦异步操作完成,调用其完成回调并执行它打算对 resolve()
或 reject()
执行的任何操作,并且已调用所有 .then()
处理程序,然后异步操作本身可能不再有对 promise 对象的引用。因此,promise 对象何时有资格进行垃圾回收将完全取决于调用代码以及它保留对 promise 的引用的时间。如果该 promise 存储在变量中,那么引用将一直存在,直到变量本身被 GC 处理或直到变量被分配了一些其他值。
or is it guaranteed to finish working as long as the process is live?
不能保证承诺会被解决或有资格进行垃圾回收。存储在持久变量(例如全局或某些持久状态)中的承诺永远不会符合垃圾收集的条件。
类似地,启动异步操作的承诺本身保留对承诺执行程序的解析或拒绝函数的引用,但从未实际完成并停留在范围内本身只会创建一个永远不会解决或拒绝的悬空承诺。
举个例子,如果您使用 webSocket 连接向远程主机发送消息,并且您设置了一个承诺,当特定响应消息从远程主机返回时解析,但响应消息永远不会返回,那么该承诺将永远等待响应消息返回。因为它仍然是 "active" 并且响应消息仍可能在未来某个时间到达,所以没有任何东西符合垃圾收集的条件。
那个承诺永远悬而未决,不会被垃圾收集。现在,在现实世界中,人们可能应该实施某种超时,如果响应没有在某种时间范围内返回,就会拒绝承诺,这将防止悬空的承诺永远持续下去,因为它仍在等待响应。
而且,如果调用者永远持有对承诺的引用,那么承诺将永远没有资格进行垃圾回收。考虑全局范围(或任何持久范围,如加载模块范围)中的这个简单示例:
var p = new Promise(function(resolve) {
setTimeout(resolve, 1000);
});
p.then(function() {
console.log("timer fired, promise resolved");
});
如果这个变量 p
永远不会超出范围并因此永远存在,那么其中的 promise help 将永远不会符合垃圾收集的条件。这与分配给 p
.
的任何其他对象没有什么不同
现在,考虑这个例子:
var p = new Promise(function(resolve) {
setTimeout(resolve, 1000);
});
p.then(function() {
console.log("timer fired, promise resolved");
});
// clear variable p
p = null;
这里,变量 p
已被清除,因此它不再保留对 promise 对象的引用。因此,一旦 p.then()
处理程序具有 运行,promise 将有资格进行垃圾收集,因为没有活动代码将不再引用该 promise。
现在,大多数时候您不必像这样手动清除 promise 变量。例如,如果上面的代码只是这样写的:
new Promise(function(resolve) {
setTimeout(resolve, 1000);
}).then(function() {
console.log("timer fired, promise resolved");
});
然后,首先没有创建持久变量p
。
或者,如果这是在一个函数范围内,它本身就会完成,例如:
function runDelay() {
var p = new Promise(function(resolve) {
setTimeout(resolve, 1000);
});
p.then(function() {
console.log("timer fired, promise resolved");
});
}
runDelay();
然后,变量 p
在 promise 触发后超出范围,因此在 promise 解析后它和 promise 本身都有资格进行 GC。
假设您有以下代码:
function startApp() {
createReallyLongRunningPromise();
// intensive work with memory
}
创建的 promise 是否有任何方法可以在完成之前进行 GC,或者只要进程处于活动状态就可以保证完成工作?
如果相关,长运行 承诺的主体 returns 本身就是一个承诺:
function createReallyLongRunningPromise() {
return new Promise(resolve => {
// Stuff
return promiseCreatedDuringStuff;
});
}
Is there any way that the created promise will get GC'd before it's done or is it guaranteed to finish working as long as the process is live?
这是两个完全独立且与某人无关的问题。 :-)
如果没有任何对象引用 promise 对象,那么它自然可以被 GC 处理。 promise 实现细节将决定 resolve
函数是否可以访问 promise 对象(而不是 promise 对象也引用的更深层次的东西);如果是这样,那么对 resolve
的任何未完成引用也将保持承诺。如果没有,那么如果没有别的,对象可以被 GC。
但这与通过 promise 报告完成的异步进程无关,除了该进程可能具有对 resolve
的活动引用并因此使 resolve
函数与resolve
函数引用的任何内容。
因此,除非环境终止,否则异步过程应该完成。你没有说你在哪里做这件事,但是例如 NodeJS 在有任何未完成的计时器、I/O 请求等时保持环境活跃。
Is there any way that the created promise will get GC'd before it's done
没有。假设异步操作仍然没有完成并且仍然有能力解决或拒绝承诺,那么它会保留对承诺对象的某种引用,因此它不能被 GC。
promise 对象只是一个普通的 Javascript 对象。它将被垃圾收集,与任何其他 Javascript 对象完全相同,即当没有活动的、可访问的代码不再引用 promise 对象时。对承诺的引用可以由正在进行的异步操作持有,也可以由异步操作的发起者和承诺的用户持有(很可能由两者共同持有)。
只要异步操作正在进行并且该异步操作的某些部分引用了承诺执行器函数的解析或拒绝回调,那么就会有一个对仍然存在的承诺对象的引用并且它根本没有资格进行垃圾收集。
一旦异步操作完成,调用其完成回调并执行它打算对 resolve()
或 reject()
执行的任何操作,并且已调用所有 .then()
处理程序,然后异步操作本身可能不再有对 promise 对象的引用。因此,promise 对象何时有资格进行垃圾回收将完全取决于调用代码以及它保留对 promise 的引用的时间。如果该 promise 存储在变量中,那么引用将一直存在,直到变量本身被 GC 处理或直到变量被分配了一些其他值。
or is it guaranteed to finish working as long as the process is live?
不能保证承诺会被解决或有资格进行垃圾回收。存储在持久变量(例如全局或某些持久状态)中的承诺永远不会符合垃圾收集的条件。
类似地,启动异步操作的承诺本身保留对承诺执行程序的解析或拒绝函数的引用,但从未实际完成并停留在范围内本身只会创建一个永远不会解决或拒绝的悬空承诺。
举个例子,如果您使用 webSocket 连接向远程主机发送消息,并且您设置了一个承诺,当特定响应消息从远程主机返回时解析,但响应消息永远不会返回,那么该承诺将永远等待响应消息返回。因为它仍然是 "active" 并且响应消息仍可能在未来某个时间到达,所以没有任何东西符合垃圾收集的条件。
那个承诺永远悬而未决,不会被垃圾收集。现在,在现实世界中,人们可能应该实施某种超时,如果响应没有在某种时间范围内返回,就会拒绝承诺,这将防止悬空的承诺永远持续下去,因为它仍在等待响应。
而且,如果调用者永远持有对承诺的引用,那么承诺将永远没有资格进行垃圾回收。考虑全局范围(或任何持久范围,如加载模块范围)中的这个简单示例:
var p = new Promise(function(resolve) {
setTimeout(resolve, 1000);
});
p.then(function() {
console.log("timer fired, promise resolved");
});
如果这个变量 p
永远不会超出范围并因此永远存在,那么其中的 promise help 将永远不会符合垃圾收集的条件。这与分配给 p
.
现在,考虑这个例子:
var p = new Promise(function(resolve) {
setTimeout(resolve, 1000);
});
p.then(function() {
console.log("timer fired, promise resolved");
});
// clear variable p
p = null;
这里,变量 p
已被清除,因此它不再保留对 promise 对象的引用。因此,一旦 p.then()
处理程序具有 运行,promise 将有资格进行垃圾收集,因为没有活动代码将不再引用该 promise。
现在,大多数时候您不必像这样手动清除 promise 变量。例如,如果上面的代码只是这样写的:
new Promise(function(resolve) {
setTimeout(resolve, 1000);
}).then(function() {
console.log("timer fired, promise resolved");
});
然后,首先没有创建持久变量p
。
或者,如果这是在一个函数范围内,它本身就会完成,例如:
function runDelay() {
var p = new Promise(function(resolve) {
setTimeout(resolve, 1000);
});
p.then(function() {
console.log("timer fired, promise resolved");
});
}
runDelay();
然后,变量 p
在 promise 触发后超出范围,因此在 promise 解析后它和 promise 本身都有资格进行 GC。