【问题标题】:Function aborts after await等待后函数中止
【发布时间】:2022-01-18 18:56:31
【问题描述】:

在浏览器扩展中我正在尝试:

  • 找到一个按钮
  • 每秒更新其文本,持续 10 秒
  • 调用提交

够简单,可惜我是 JavaScript 新手。

我一无所知:为什么下面的代码没有到达第 15 行(等待之后)?

const Timeout = 10000;
const CountdownStep = 1000;

async function scheduleSubmit(node, timeout) {
  originalTextContent = node.textContent;
  while (timeout > 0) {
    console.log(`Timeout: ${timeout}`);
    try {
      await new Promise((resolve => setTimeout(() => {
        console.log(`[Promise] Timeout: ${timeout}`);
        node.textContent = `${originalTextContent} (${timeout / 1000})`;
        timeout -= CountdownStep;
        console.log(`[Promise] Timeout: ${timeout}`);
      }, CountdownStep)));
      console.log('Hello? Helloooooooo??');
    } catch (err) {
      log(`Error: ${err}`);
    }
  }
  node.submit();
}

scheduleSubmit(document.getElementById('foo'), Timeout);
<html><body>
<button type="button" id="foo">Run</button> 
</body></html>

【问题讨论】:

  • 你必须通过调用resolve()来解决你的承诺
  • 将您的 setTimeout-wrapper-Promise 移动到单独的函数中。
  • Protip:在已经是async 的函数中使用Promise 的原语(例如new Promise,尤其是.then())总是一个坏主意。虽然它并非不正确,但它常常让必须阅读您的代码的人感到困惑。此外,您的代码具有嵌套 3 层深的闭包,这足以让我想将它们全部撕掉并将它们移动到命名函数。
  • @Dai,谢谢,这是很好的反馈。

标签: javascript promise


【解决方案1】:

如果您提取一个简单的 delay 帮助器,该帮助器返回一个 Promise,该 Promise 在指定的时间后解决,您的代码变得更具可读性。更不用说您可以单独测试和调试代码以识别问题。

const SUBMIT_TIMEOUT = 10000;
const COUNT_DOWN_STEP = 1000;

function delay(timeout) {
  return new Promise(resolve => setTimeout(resolve, timeout))
}

async function scheduleSubmit(node, timeout) {
  const originalTextContent = node.textContent;
  while (timeout > 0) {
    try {
      await delay(COUNT_DOWN_STEP);
      
      node.textContent = `${originalTextContent} (${timeout / 1000})`;
      timeout -= COUNT_DOWN_STEP;
    } catch (err) {
      log(`Error: ${err}`);
    }
  }
  node.submit();
}

scheduleSubmit(document.getElementById('foo'), SUBMIT_TIMEOUT);
<html><body>
<button type="button" id="foo">Run</button> 
</body></html>

【讨论】:

  • 支持 更简洁 代码(我想我会将const Timeoutconst CountdownStep 重命名为使用_conventional UPPER_SNAKE_CASE 样式为const SCHEDULE_TIMEOUTconst SCHEDULE_COUNTDOWN_STEP ,因为使用“超时”这样的通用名称是个坏主意)。
【解决方案2】:

你只需要调用resolve()来解析Promise:

const Timeout = 10000;
const CountdownStep = 1000;

async function scheduleSubmit(node, timeout) {
  originalTextContent = node.textContent;
  while (timeout > 0) {
    console.log(`Timeout: ${timeout}`);
    try {
      await new Promise((resolve => setTimeout(() => {
        console.log(`[Promise] Timeout: ${timeout}`);
        node.textContent = `${originalTextContent} (${timeout / 1000})`;
        timeout -= CountdownStep;
        console.log(`[Promise] Timeout: ${timeout}`);
        resolve();
      }, CountdownStep)));
      console.log('Hello? Helloooooooo??');
    } catch (err) {
      log(`Error: ${err}`);
    }
  }
  node.submit();
}

scheduleSubmit(document.getElementById('foo'), Timeout);
<html><body>
<button type="button" id="foo">Run</button> 
</body></html>

文档:https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise

【讨论】:

  • 太好了,谢谢!
  • Np 很高兴我能帮上忙 :)
猜你喜欢
  • 2014-03-23
  • 1970-01-01
  • 1970-01-01
  • 2019-12-12
  • 2023-03-13
  • 1970-01-01
  • 2021-09-23
  • 1970-01-01
  • 2019-08-18
相关资源
最近更新 更多