概述
JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊。
JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?
为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。
JS异步的发展史
回调函数 -> generator -> Promise -> Async、Await
JS执行环境中负责执行代码的线程只有一个
一个线程情况下,有多个同步任务只能排队进行处理,这样的模式优点是更安全更简单,缺点就是会有任务阻塞的情况,出现假死情况。所以JS有了同步模式和异步模式。
同步模式和异步模式
JavaScript是单线程的,但是浏览器执行环境并不是单线程的,通过JS调用的一些内部Api它也不是单线程的,例如setTimeout 等浏览器自带API是单独工作的,不受JS单线程影响。
回调函数
由调用者定义,交给执行者执行的函数就是回调函数
Promise
CommonJS社区提出了Promise的规范,在ES2015中被标准化,成为语言规范。在模拟promise时可以使用自带生成异步的Api。Promise本质上也是使用回调函数定义异步任务结束后所需要执行的任务。
unhandledrejection事件
处理代码中没有被手动捕获的Promise异常
宏任务和微任务
微任务有一方面是为了提高应用的整体响应能力。可看作每个宏任务后面都跟着一个微任务队列,每执行完一个宏任务会先清空其微任务队列,再执行下一个宏任务。
generator异步编程
了解generator ES5实现方式
记录一个批量操作方法
const messageQueue = [];
const sendMessage = message => {
messageQueue.push(message);
if (messageQueue.length === 1) {
queueMicrotask(() => {
const json = JSON.stringify(messageQueue);
messageQueue.length = 0;
// fetch("url-of-receiver", json);
console.log(json);
});
}
};