promise规范

46 阅读3分钟

异步解析

  • 什么是异步?
// 异步执行
let count = 1;
let timer = setTimeout(() => {
  count++;
  console.log("in", count);
}, 1000);
console.log("out", count);

// 循环执行
let count = 1;
let timer = setInterval(() => {
  count++;
  console.log("in", count);
});
setTimeout(() => {
  clearInterval(timer);
}, 5000);

1.进程 & 线程

概念 & 区别

  • 进程:CPU 资源分配的最小单位
  • 线程:CPU 调度的最小单位

面试题:浏览器打开一个新窗口,是进程还是线程? --- 进程

  • 发散
  1. 方向一:窗口(进程)间通信? - storage | cookie => 多种存储区别和联系 => 安全性 => 回归项目
  2. 方向二:浏览器原理(中高级岗位)
页面(进程)
  1. GUI 渲染线程
    • 解析 HTML|CSS,构建 DOM 树
    • 与 JS 引擎互斥,当执行 JS 时,GUI 渲染会被挂起
  2. JS 引擎
    • 处理 JS,解析执行脚本
    • 处理待执行逻辑,安排事件队列有序执行
    • 阻塞 GUI 线程 => 使得与 GUI 渲染线程互斥进行 => 面试:为什么?确保渲染效果的一致性
  3. 定时器线程
    • 异步定时器的处理与执行
    • 接收 JS 引擎分配的定时器任务并执行
    • 处理完成后交给事件触发线程
  4. 异步 http 请求线程
    • 异步执行网络类的操作
    • 接收 JS 引擎分配的网络类请求的任务并执行
    • 监听回调处理完后交给事件触发线程
  5. 事件触发线程
    • 接收所有来源的事件
    • 把接收到的回调事件按照顺序加入到任务队列的队尾,做好排序后交给 JS 引擎

2. EVENT-LOOP 事件循环

  • 存储堆:分配内存,先入先出
  • 执行栈:执行调用,先入后出
  • 任务队列:先进先出
  • 事件循环:监视执行栈和任务队列,当执行栈为空时,事件循环从任务队列中取第一个任务,放入执行栈执行,这个过程不断重复,直到任务队列为空

任务队列 TASK QUEUE

  • 任务队列:当异步操作完成时(例如, setTimeout 、 Promise 的 .then 方法、事件监听器等),相应的回调函数会被放入任务队列中,等待被执行
  • 宏任务(Macro):setTimeout 、 setInterval 、I/O 操作等
  • 微任务(Micro):Promise 的回调、 MutationObserver

promise

a.回调地狱

b.面试 Promise A+

  1. promise 有哪些状态?对应值有哪些? promise:pending | fulfilled | rejected executor:new Promise 时需要立即执行,接收两个参数 resolve + reject
  2. promise 默认状态时什么?状态如何扭转? 默认状态:pendng 内部维护成功值:undefined | thenable | promise 内部维护失败值:reason 状态流转:pending => fulfilled | pending => rejected
  3. promise 返回值? then:接收 onFulfilled 或者 onRejected 如果 then,promise 成功,执行 onFulfilled,参数 value 如果 then,promise 成功,执行 onRejected,参数 reason then 中任何的 error,执行 onRejected

面试 : 手写 promise

const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
class Primise {
  constructor(executor) {
    // 1.默认状态 - pending
    this.status = PENDING;
    // 2.维护内部值
    // 值
    this.value = undefined;
    this.reason = undefined;
    // 回调
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    // pending => fulfilled | pending => rejected
    // 成功回调
    let resolve = (value) => {
      if (this.status === PENDING) {
        this.status = FULFILLED;
        this.value = value;
        this.onResolvedCallbacks.forEach((fn) => fn());
      }
    };
    // 失败回调
    let resolve = (reason) => {
      if (this.status === PENDING) {
        this.status = REJECTED;
        this.reason = reason;
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    };
    // 主执行
    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  then(onFulfilled, onRejected) {
    if (this.status === FULFILLED) {
      onFulfilled(this.value);
    }
    if (this.status === REJECTED) {
      onRejected(this.reason);
    }
    if (this.status === PENDING) {
      this.onResolvedCallbacks.push(() => {
        onFulfilled(this.value);
      });
      this.onRejectedCallbacks.push(() => {
        onRejected(this.reason);
      });
    }
  }
}