【问题标题】:I think I understand async, await, promises and callbacks but I have a question about asynchronous code [duplicate]我想我了解异步、等待、承诺和回调,但我对异步代码有疑问 [重复]
【发布时间】:2019-03-24 21:13:52
【问题描述】:

所以我目前正在尝试了解异步 javascript。我了解了异步等待、承诺和回调。但在所有示例中,他们都使用setTimeOut() 来生成异步调用。

但我的问题是如何编写类似setTimeOut 函数的东西。例如,我有一个需要时间的大计算,我希望它不会阻塞主线程。我将如何制作一个只计算很多东西但异步的函数?

我只是无法理解这一点。因为在我看来只能通过网络调用等编写异步代码,但我还没有找到一种方法来编写像 async for 循环或类似的东西。

【问题讨论】:

  • 在主函数中使用回调...
  • 使用常规的旧 javascript 您不需要,您只需使用一个线程即可。如果你需要这样做,你将需要类似web workers(或在node.js 中child procceses)来生成另一个线程/进程。
  • 他们不使用Timeout()生成一个异步函数,他们使用它模拟一个需要时间执行的动作,因此演示 async 的实际工作原理
  • 您通过在每次迭代(或迭代块)之间执行setTimeout 来编写一个异步循环。

标签: javascript asynchronous


【解决方案1】:

您似乎没有完全掌握异步是什么。这个词本身说它是“不同步的”。这意味着有些运动部件不会以相同的速度或速度运动。对于 JavaScript,它归结为 I/O(输入/输出)和 CPU 处理。

网络调用 (xhr) 是与 CPU 处理速度相比速度较慢的 I/O 调用。

文件系统调用是比 CPU 处理速度慢的 I/O 调用。

数据库查询是利用网络的 I/O 调用,与 CPU 的处理速度相比速度较慢。

使用异步代码的逻辑是“让 CPU 在这个东西通过网络或其他线路传输时做其他事情”。

为什么要这么多介绍?因为你不能进行异步的大计算。它利用CPU。但是,您可以在 service worker 中执行它,让它使用不同的 CPU 内核,并且不会阻塞主线程。

Service Worker 简介:https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API

【讨论】:

    【解决方案2】:

    你不能¹。要执行异步任务,您需要某种方式在另一个线程上运行代码,而这在 JavaScript 中是不可能的。

    setTimeout 是异步的,因为它触发了一个用某种低级语言(可能是 C++)编写的内部函数,然后该函数将利用硬件计时器来触发在一段时间后调用的回调。

    fetch(...) 例如也是异步的,因为它会启动一个内部线程,通过你的网卡进行读写,然后在请求完成后回调 JavaScript 引擎。


    ¹这有点过于简单了。您可以启动多个 WebWorker(同时运行多个 JavaScript 引擎)来获得某种多线程。虽然代码仍然每个线程同步运行,但两个线程可以并发执行并通过消息交换信息,通过这些您可以获得异步行为。

      // worker.js
      onmessage = function({ data }) { // called when messages from the other thread come in
        let start = Date.now();
        while(start + 3000 > Date.now()); // some long running action
       postMessage("done"); // go back to the other thread
     }
    
     // main.js
     const otherThread = new WebWorker("worker.js");
     otherThread.postMessage("go!"); // launch async task in other thread
     otherThread.onmessage = function({ data }) { // receive result
      console.log(data); // "done"
     });
    

    WebWorker documentation

    【讨论】:

    • 好的,我想我的问题应该是如何编写多线程代码?
    • @waterchiller 已编辑以包含该内容
    • 好的,非常感谢。所以这基本上就是 setTimeOut 和网络调用的作用?
    • @waterchiller 是的,有点,只是在另一个线程中运行的代码不是 JavaScript,而是一些编译后的东西,也可以直接利用硬件。
    • 好的,谢谢,看起来有点复杂。在swift中多线程要容易得多
    猜你喜欢
    • 2019-05-05
    • 2018-09-02
    • 2018-04-17
    • 2018-03-02
    • 2017-06-15
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    • 2021-10-07
    相关资源
    最近更新 更多