所以我目前正在尝试了解异步javascript。我了解了异步等待,承诺和回调。但是在所有示例中,它们都使用setTimeOut()
来生成异步调用。
但是我的问题是如何编写类似setTimeOut
的函数。例如,我有一个很大的计算,要花一些时间,我希望它不阻塞主线程。我将如何创建一个仅计算大量内容但异步的函数?
我只是无法解决这个问题。因为在我看来,只能通过网络调用等来编写异步代码,但是我还没有找到像异步for循环这样的方法来编写代码。
答案 0 :(得分:1)
您似乎没有完全理解异步是什么。这个词本身表示“未同步”。这意味着有些运动部件的运动速度或速度不同。如果使用JavaScript,则可以归结为I / O(输入/输出)和CPU处理。
网络调用(xhr)是与CPU处理速度相比较慢的I / O调用。
文件系统调用是与CPU可以处理的速度相比较慢的I / O调用。
数据库查询是利用网络的I / O调用,与CPU可以处理的速度相比要慢。
带有异步代码的逻辑是“在此事情通过网络或其他线路传输时,让CPU做其他事情”。
为什么所有这些简介?因为您不能使大型计算异步进行。它利用CPU。但是,您可以在服务工作者中执行它,让它使用其他CPU内核,并且不会阻塞主线程。
服务人员简介:https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
答案 1 :(得分:1)
你不能¹。要执行异步任务,您需要某种方式在另一个线程上运行代码,而这在JavaScript中是不可能的。
setTimeout
是异步的,因为它会触发用某种底层语言(可能是C ++)编写的内部函数,该函数随后将利用硬件计时器触发将在一段时间后调用的回调。
fetch(...)
也是异步的,因为它将启动一个内部线程来读写您的网卡,然后在请求完成后回调JavaScript引擎。
¹有点简化。您可以启动多个WebWorkers(同时运行多个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"
});