【问题标题】:ClearTimeout usage best practice within a promise承诺中的 ClearTimeout 使用最佳实践
【发布时间】:2018-10-12 01:12:07
【问题描述】:

我有一个关于 clearTimeout 方法的问题(对于菜鸟问题​​提前抱歉)。我想知道在以下代码中清除超时的最佳位置在哪里?我有一个“getResponse()”函数,它将被多次调用。我不确定在哪里放置 clearTimeout 的最佳位置,以便在 responseTimeout 解决或拒绝后立即清除超时。谢谢

function getResponse() {
    const responseTimeout = new Promise((resolve, reject) => {
        let id = setTimeout(() => {
            if (!messageHandled) {                       
                reject(`Timed out to get response`);               
            }                      
        }, 3000);
    });

    const responsePromise = new Promise((resolve, reject) => {
        // some code which returns response promise
    });

    return Promise.race([
        responsePromise,
        responseTimeout
    ]);
}

【问题讨论】:

  • 在给定的代码中,您没有调用clearTimeout,是不是忘记添加了?但无论如何,您实际上根本不需要清除它。你的 promise.race 只会被解决一次,即第一个要解决的承诺,并且会忽略另一个。所以你目前拥有的应该没问题。
  • 我没有忘记它,我不知道该放在哪里。在 Promise.race 中,当第一个需要更长的时间并且 timeoutpromise 拒绝时,我应该清除超时吗? getResponse 函数将被多次调用,这就是我要清除它的原因。如果我的想法不正确,请告诉我
  • 更新了问题以使其更清晰
  • 啊,我以为这个代码块就是你所说的初稿。就个人而言,我不会清除它,将一个简单的承诺拒绝被默默地忽略并没有什么坏处,而保持复杂的闭包只是为了能够取消这个非常小的超时执行将产生更复杂的维护代码。但那是意见。 + 我不知道在 GC 方面永远未决的 Promise 会发生什么。实际上,根本不清除超时可能会更好。但是如果你真的想做,那就在getResponse里面初始化id,然后在responsePromise里面清除。

标签: javascript settimeout cleartimeout


【解决方案1】:

通常,我会在 Promise 本身中执行此操作,并避免两个单独的 Promise 的开销。

function getResponse(...params) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject(new Error("Timed out to get response"))

      // some code to abort request
    }, 3000)

    // some code which resolves promise
  })
}

有用的是,在你第一次解决之后,promise 会忽略以后的解决和/或拒绝。如果您可以在不触发解析逻辑的情况下以编程方式中止它,这将变得容易得多,但即使您不能,您也可以随时添加一个布尔值来阻止未来的请求。它还可以更轻松地添加对稍后取消的支持,这也很有帮助。如果您还需要关闭超时(如果您正在执行一些 DOM 突变或文件读取 - 您很少需要这样做),您可以执行以下操作:

function getResponse(...params) {
  return new Promise((reallyResolve, reallyReject) => {
    let resolved = false
    let id = setTimeout(() => {
      reject(new Error("Timed out to get response"))
      abort()
    }, 3000)

    // I'll use these instead of the `resolve`/`reject` callbacks directly.
    function resolve(value) {
      if (resolved) return
      resolved = true
      clearTimeout(id)
      reallyResolve(value)
    }

    function reject(value) {
      if (resolved) return
      resolved = true
      clearTimeout(id)
      reallyReject(value)
    }

    function abort() {
      // some code to abort request
    }

    // some code which resolves promise
  })
}

这样我就不必担心协调一切,但它仍然有效。

如果你不需要中止逻辑(你只需要它来处理网络请求和类似的事情),这会变得简单得多:

function timeout(ms) {
  return new Promise((_, reject) => {
    setTimeout(() => reject(new Error("Timed out")), ms)
  })
}

function getResponse(...params) {
  return Promise.race([
    timeout(3000),
    doSomethingAsync(),
  ])
}

【讨论】:

  • @Kaiido 已修复。谢谢你的收获。 (我很少使用Promise.race 我有时几乎忘记了它。)
猜你喜欢
  • 2017-12-12
  • 1970-01-01
  • 2014-02-24
  • 1970-01-01
  • 2017-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多