JavaScript异步编程-笔记

110 阅读2分钟

概述

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);
    });
  }
};