promise剖析

一、定义

promise是js异步的一种解决方案

1. js为什么要实现异步

js代码首先是单线程执行,即同步执行,正常来讲是在一个线程上有一个执行栈,全局/函数/eval执行上下文根据调用依次压入栈中,执行完后从栈中弹出,先进后出。如果碰到I/O任务,响应会比较慢,这样就会导致以下的问题:

  • 造成网页卡死,因为js引擎线程和GUI渲染线程是互斥的,js任务队列没有执行完毕,GUI渲染线程一直被挂起
  • 这时候CPU往往是闲着的,浪费了资源
    那么为了解决上述问题,就需要js实现异步来解决阻塞问题,将一些需要等待响应的任务作为异步任务,放入任务队列,等待执行栈中的当前任务执行完后,将任务队列推入主线程,依次执行任务队列中的任务。

2. 解决方案是怎样的

3. 还有什么解决方案,它们的区别

4. 自己实现一种方案

什么是单线程语言?

浏览器架构

浏览器是多进程架构,一个tab网页即一个进程,各个tag网页间互不干扰,完全独立。每打开一个tab网页,浏览器就会为该网页分配独立的渲染引擎实例。

渲染引擎(浏览器内核)

渲染引擎即浏览器内核是多线程的,在内核的控制下各线程相互配合以保持同步,这些线程主要包括:

  • GUI渲染线程
    负责渲染HTML元素,当页面需要重绘repaint/回流reflow时,该线程就会执行。
  • JavaScript引擎线程
    负责解析js脚本,运行代码,我们常说的V8引擎就是一个js引擎。
  • 定时触发器线程
    setTimeout、setInterval等待时间结束后把执行函数堆入任务队列中
  • 事件触发线程
    将click、mouse等交互事件发生后将这些事件放入事件队列中
  • 异步http请求线程
    处理用户的get、post等请求,等返回结果后将回调函数堆入任务队列
总结

从以上内容可以看出,js代码是被一个js引擎线程来解析执行,即单线程执行,所以说js是单线程语言

为什么是单线程语言

这主要是因为js脚本的作用是处理用户的交互,操作dom,如果做成来多线程的话,一旦dom操作达到临界资源,开启了一个新的线程来执行,而两个线程分别是修改和删除同一个dom,就会出现问题(该问题可以通过锁来解决,但是可能会造成其他的问题,大大增加复杂性)。

如何实现多线程

为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

GUI渲染线程和JS引擎线程是互斥的

JavaScript事件循环机制