Bluebird 承诺使用,它会泄漏吗?

Bluebird promise usage, does it leak?

我不太了解promises中的内存模型。我正在使用蓝鸟 2.x.

我有类似的东西试图连接到蓝牙设备。我想要它,这样如果它在 10 秒内无法连接,我想关闭它并 return 它作为失败。

Control.prototype.connectToAddress = function connectToAddress(address)
{
  var self = this;

  return new Promise(function(resolve, reject) {

    var timer = setTimeout(function() {
      reject(new Error('Timeout'));
    }, 10000);

    self.bt.connectToAddressAndService(address, self.service)
    .then(function(dev) {
      clearTimeout(timer)
      resolve(dev);
    })
    .then(function error(err) { reject(err); });

  });
}

这不是实际情况。实际情况是 connectToAddress 立即解析,无需等待设备连接。稍后设置发射器以通知调用者已找到设备。但是为了这个问题,假设 connectToAddress 实际上在等待并且 return 连接的设备。

当我们在 10 秒内无法连接到设备时,也许它在我们扫描后就离开了,承诺被拒绝。但是,self.bt.connectToAddressAndService 呼叫尚未解决以解决或拒绝。如果在这种情况下重复调用 connectToAddress,是否会导致某种内存堆栈堆积而永远不会释放?如果是这样,我该怎么做才能避免这种情况?

Promises 只是 Javascript 个对象,就像任何其他 Javascript 对象一样被垃圾收集。因此,只要您不无限期地保留对 promises 的引用,当它们不再被使用时,它们将像任何其他对象一样被垃圾回收。

因此,在您的特定示例中,只要您的计时器仍在运行或 .connectToAddressAndService() 仍在做某事并且可能仍然能够拒绝或解决(这意味着它仍然具有对解析或拒绝处理程序的实时引用)。定时器显然有 10 秒的固定寿命。但是,您没有显示 .connectToAddressAndService() 背后的代码,因此我们无法真正提供有关它可能存活多长时间的任何信息。它确实应该是这样的情况,它会在某个时候解决或拒绝,所以它不可能永远挂起以保持这种内部状态。我们必须查看其中的代码才能知道当前是否存在问题。

如果您的操作已超时,但 .connectToAddressAndService() 仍然存在并且会在未来很长一段时间内调用它自己的解析或拒绝处理程序,那么在等待时仍有内存在使用最终完成。即使承诺已被拒绝,Javascript 也不知道您在 .connectToAddressAndService() 周围的其他代码可能在做什么,因此您显示的代码中的内部状态会保持活动状态并保存在内存中。