我读了很多关于异步操作的内容,但总是缺少一件事,所以我想问一下。
当异步操作注册并开始运行时,我们简单地说;在后台完成这项工作,并且不要让调用异步函数的线程忙碌。但与此同时,异步操作或函数继续在后台运行。它实际上是如何在后台运行的?操作系统分配给此操作的另一个线程是否可以执行此异步任务或什么?
异步操作会向主线程发送一些消息/信号,可能是结束进程的进程信号,也可能是结束文件读取操作的文件系统消息,或者是网络消息。
顺便说一句,您可以自己创建线程作为网络工作者,并将消息发送回主线程,以便它可以解决承诺,并且主线程上的代码会知道异步操作已完成。学习这个例子有望有助于理解 JS 中的异步操作是如何完成的:
let taskId = 1;
const executeFunctionInWorker = function(fn){
const id = taskId++;
return new Promise(resolve => {
const blob = new Blob([`
let start = performance.now();
(${fn.toString()})();
postMessage({duration: performance.now() - start});
`], {type: 'application/javascript'});
const worker = new Worker(URL.createObjectURL(blob));
worker.addEventListener('message', e => {
resolve(`Finished task ${id} in ${e.data.duration}ms`);
});
});
};
const doComputation = () => {
let count = 1000;
while(count--){
structuredClone(Array.from({length: 5000}, () => Math.random()));
}
};
class PromiseQueue{
tasks = [];
async push(task){
const starting = this.tasks.length === 0;
this.tasks.push(task);
if(starting){
let task;
while(task = this.tasks[0]){
const result = await task();
this.tasks.shift();
console.log(result);
}
}
}
};
const queue = new PromiseQueue;
const push = () => Array.from({length: 5}, () => queue.push(() => executeFunctionInWorker(doComputation)));
<button onclick="push()">Queue 5 tasks</button>
<div>You can press any number you want without waiting the previous tasks to complete</div>