RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1424355
Accepted
user507812
user507812
Asked:2022-08-27 18:32:26 +0000 UTC2022-08-27 18:32:26 +0000 UTC 2022-08-27 18:32:26 +0000 UTC

如何使用 async/await 等待 setTimeout 完成

  • 772

有一个任务,简单如耙子。三个操作 - 两个同步,它们之间的一个异步。异步任务必须连续第二个执行,而不是最后一个。计算的最终结果应该等于 1。如何使用async/await语法来实现这一点,而不使用全局 Promise 对象。下面是一个示例解决方案,但不正确。

为什么我需要这个,这个奇怪的代码是什么,它有什么意义,等等。这些问题都没有了。我花了几天时间解决这个问题,我联系的每个人都无法解决它。只是为了这个任务,我在这个网站上注册了,所以这对我来说很重要。

const summarize = (num1, num2) => num1 + num2;
const divide = (num1, num2) => num1/num2;

let x = 2;
let y = 6;
let z = 10;

const calcAsync = async () => {
  x = summarize(x, x);                           // (1шаг) 2 + 2 = 4
  x = await setTimeout(() => summarize(x, y), 1);// (2шаг) ??? должно получится 4 + 6 = 10
  x = divide(x, z);                              // (3шаг) ??? должно получится 10/10 = 1
}

calcAsync();
javascript async-await
  • 3 3 个回答
  • 174 Views

3 个回答

  • Voted
  1. EzioMercer
    2022-08-27T19:00:31Z2022-08-27T19:00:31Z

    您应该将其包装setTimeout在Promise中:

    const summarize = (num1, num2) => num1 + num2;
    const divide = (num1, num2) => num1 / num2;
    
    let x = 2;
    let y = 6;
    let z = 10;
    
    const calcAsync = async() => {
      x = summarize(x, x);
      
      console.log(1, x);
      
      x = await new Promise((resolve, reject) => {
        setTimeout(() => resolve(summarize(x, y)));
      });
      
      console.log(2, x);
      
      x = divide(x, z);
      
      console.log(3, x);
    }
    
    calcAsync();

    解释为什么你不能没有Promise:

    PS 形式上,这种说法是不正确的。正如@GrundyPromise所示,将其替换为最普通thenable的对象(具有方法的对象)就足够了then,在这种情况下,一切都将与 with 完全相同Promise。但是这个答案会让您了解为什么await-tit 或 wrap in asyncf- yu 无济于事setTimeout

    考虑这段代码:

    const calcAsync = async () => {
      x = summarize(x, x);
      x = await setTimeout(() => summarize(x, y), 1);
      x = divide(x, z);
    }
    

    因为 async/await返回并运行Promise,然后让我们将这段代码翻译成Promise-ov 语言:

    const calcAsync = () => {
      return Promise.resolve()
        .then(function () {
          x = summarize(x, x);
    
          return setTimeout(() => summarize(x, y), 1);
        })
        .then(function (handleResolved) {
          x = handleResolved;
          x = divide(x, z);
        });
    };
    

    所以我们对带有 的字符串感兴趣setTimeout。文档说它将从 -a -thisthen接收2 个参数,并且还说它也会返回。我们只对 感兴趣,因此将进一步省略。所以第二个输入将收到一个返回值——这是timeoutID的数量,启动什么函数以及何时启动都无关紧要。因此,在第二个中,其中的行将被写入数字PromisehandleResolvedhandleRejectedPromisehandleResolvedhandleRejectedthensetTimeoutthenx = handleResolvedxtimeoutID并将使用该值进行进一步的计算。重要的是,这个数字每次都会不同,在一个会话中重新启动相同的代码会给你不同的值。

    演示代码(特意去掉x = await...,以免他们认为一切都是因为x它被写入了某个东西):

    const summarize = (num1, num2) => num1 + num2;
    const divide = (num1, num2) => num1 / num2;
    
    let x = 2;
    let y = 6;
    let z = 10;
    
    const calcAsync = async() => {
      x = summarize(x, x);
    
      console.log(await setTimeout(() => summarize(x, y)));
      console.log(await setTimeout(() => summarize(x, y)));
      console.log(await setTimeout(() => summarize(x, y)));
      console.log(await setTimeout(() => summarize(x, y)));
    
      x = divide(x, z);
    }
    
    calcAsync();

    我们还需要获取x第二个中的值。thensummarize(x, y)

    作者提出了一个选项来包装setTimeoutf async-th 因为。async返回给我们Promise。我注意到在包装器中写这样的东西就像return await setTimeout没有包装器一样没用。让我们看看在这种情况下会发生什么:

    const asyncSum = async () => {return setTimeout(() => summarize(x, y), 1)}
    
    const calcAsync = async() => {
      x = summarize(x, x);
      
      x = await asyncSum();
      
      x = divide(x, z);
    }
    

    将其重写为Promise-ov 我们得到:

    const asyncSum = () => {
      return Promise.resolve().then(function () {
        return setTimeout(() => summarize(x, y), 1);
      });
    };
    
    const calcAsync = () => {
      return Promise.resolve()
        .then(function () {
          x = summarize(x, x);
    
          return asyncSum();
        })
        .then(function (handleResolved) {
          x = handleResolved;
          x = divide(x, z);
        });
    };
    

    现在我们可以安全地将函数的结果替换asyncSum为调用它的位置并得到:

    const calcAsync = () => {
      return Promise.resolve()
        .then(function () {
          x = summarize(x, x);
    
          return Promise.resolve().then(function () {
            return setTimeout(() => summarize(x, y), 1);
          });
        })
        .then(function (handleResolved) {
          x = handleResolved;
          x = divide(x, z);
        });
    };
    

    我们看到了什么?我们再次发送到handleResolved我们timeoutID的。因此,这里的包装器也无助于发送值本身summarize(x, y)

    现在我们弄清楚了为什么不能await包装async我们的,让我们看看-thsetTimeout包装器如何帮助我们:Promise

    const calcAsync = async() => {
      x = summarize(x, x);
      
      x = await new Promise((resolve) => {
        setTimeout(() => resolve(summarize(x, y)), 1);
      });
      
      x = divide(x, z);
    }
    

    我们再次将其重写为Promise-ov 语言并得到:

    const calcAsync = () => {
      return Promise.resolve()
        .then(function () {
          x = summarize(x, x);
    
          return new Promise((resolve) => {
            setTimeout(() => resolve(summarize(x, y)), 1);
          });
        })
        .then(function (handleResolved) {
          x = handleResolved;
          x = divide(x, z);
        });
    };
    

    现在您可以看到我们在字符串中显式handleResolved传递了 f-ii 的值。这里的重点是,在调用/解决下一个之前,下一个将等待,无论需要多长时间summarize(x, y)resolve(summarize(x, y))resolvethen

    PS文档说这段代码:

    async function foo() {
       return 1
    }
    

    如同:

    function foo() {
       return Promise.resolve(1)
    }
    

    但我将其重写为:

    function foo() {
      return Promise.resolve().then(function () {
        return 1;
      });
    }
    

    在论点和示例本身中,这不会影响任何事情。如果按照文档中所示重写,整个逻辑将完全相同,但为了不经常在方法resolve和之间切换then,我决定如果总是then有 ,那么混乱就会减少,这将有助于更好地理解什么正在发生。我希望我能够做到这一点:)

    • 6
  2. Best Answer
    Grundy
    2022-08-28T21:55:32Z2022-08-28T21:55:32Z

    您可以使用await可以应用于thenable对象的东西,即带有then.

    与构造函数类似Promise,该方法then也接受两个参数resolve和reject。

    const summarize = (num1, num2) => num1 + num2;
    const divide = (num1, num2) => num1 / num2;
    
    let x = 2;
    let y = 6;
    let z = 10;
    
    const calcAsync = async() => {
      x = summarize(x, x); // (1шаг) 2 + 2 = 4
      console.log('(1шаг)', x);
      x = await {
        then(r) {
          setTimeout(() => r(summarize(x, y)), 1)
        }
      }; // (2шаг) ??? должно получится 4 + 6 = 10
      console.log('(2шаг)', x);
      x = divide(x, z); // (3шаг) ??? должно получится 10/10 = 1
      console.log('(3шаг)', x);
    }
    
    calcAsync();

    • 3
  3. Qwertiy
    2022-08-27T19:35:08Z2022-08-27T19:35:08Z
    await setTimeout(() => summarize(x, y), 1);
    
    1. setTimeoutawait立即返回定时器的id,从这里没有意义。
    2. summarize并且通常不使用调用的结果。
    3. 1ms 很奇怪。最有可能在这里和零或缺少的论点还不错。

    它应该是这样的:

    x = await new Promise(resolve => setTimeout(resolve, 0, summarize(x, y)))
    

    尽管在任何情况下,整个构造都假设结果是同步已知的,因此尚不清楚它为什么会发生。

    只需要有async/await,没有Promise,没有then(),代码应该尽量和同步类似。

    它不会那样工作:await它适用于then.

    • -1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5