异步解析
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 调度的最小单位
面试题:浏览器打开一个新窗口,是进程还是线程? --- 进程
- 方向一:窗口(进程)间通信? - storage | cookie => 多种存储区别和联系 => 安全性 => 回归项目
- 方向二:浏览器原理(中高级岗位)
页面(进程)
- GUI 渲染线程
- 解析 HTML|CSS,构建 DOM 树
- 与 JS 引擎互斥,当执行 JS 时,GUI 渲染会被挂起
- JS 引擎
- 处理 JS,解析执行脚本
- 处理待执行逻辑,安排事件队列有序执行
- 阻塞 GUI 线程 => 使得与 GUI 渲染线程互斥进行 => 面试:为什么?确保渲染效果的一致性
- 定时器线程
- 异步定时器的处理与执行
- 接收 JS 引擎分配的定时器任务并执行
- 处理完成后交给事件触发线程
- 异步 http 请求线程
- 异步执行网络类的操作
- 接收 JS 引擎分配的网络类请求的任务并执行
- 监听回调处理完后交给事件触发线程
- 事件触发线程
- 接收所有来源的事件
- 把接收到的回调事件按照顺序加入到任务队列的队尾,做好排序后交给 JS 引擎
2. EVENT-LOOP 事件循环
- 存储堆:分配内存,先入先出
- 执行栈:执行调用,先入后出
- 任务队列:先进先出
- 事件循环:监视执行栈和任务队列,当执行栈为空时,事件循环从任务队列中取第一个任务,放入执行栈执行,这个过程不断重复,直到任务队列为空
任务队列 TASK QUEUE
- 任务队列:当异步操作完成时(例如, setTimeout 、 Promise 的 .then 方法、事件监听器等),相应的回调函数会被放入任务队列中,等待被执行
- 宏任务(Macro):setTimeout 、 setInterval 、I/O 操作等
- 微任务(Micro):Promise 的回调、 MutationObserver
promise
a.回调地狱
b.面试 Promise A+
- promise 有哪些状态?对应值有哪些?
promise:pending | fulfilled | rejected
executor:new Promise 时需要立即执行,接收两个参数 resolve + reject
- promise 默认状态时什么?状态如何扭转?
默认状态:pendng
内部维护成功值:undefined | thenable | promise
内部维护失败值:reason
状态流转:pending => fulfilled | pending => rejected
- 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) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
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);
});
}
}
}