promise 解析
- 异步操作
// 异步执行
let timer = setTimeout(() => {
console.log("in"); // 异步
}, 1000)
console.log("out") // 同步
// 执行顺序:out in
// 异步执行+终止
let count = 1;
let timer = setInterval(() => {
count ++
console.log("in", count); // 异步
}, 1000)
console.log("out") // 同步
setTimeout(()=>{
clearInterval(timer);
console.log("in", count); // 异步
}, 5000)
console.log("out", count) // 同步
1. 进程和线程
a. 概念与区别
计算机原理:进程是CPU资源分配的最小单位,线程是CPU调度的最小单位。
浏览器原理(中高级)
* 浏览器的各个标签页就是进程 => 进程,从区别概念上出发【a标签页进入死循环,b标签页不受影响】
* 发散:方向一:窗口(进程间)如何通信? => storage,cookie => 多种存储的区别
* 发散:方向二:浏览器原理(中高级)
浏览器原理 ---- 浏览器页面:
a. GUI渲染引擎 -- 1.解析HTML、CSS,构建DOM树 => 布局 => 绘制;2. GUI引擎和JS引擎是互斥的,当执行JS引擎线程时,GUI会pending,当任务队列空闲时,才会执行GUI
b. js引擎线程 -- 1.处理js,解析执行javaScript;2.分配处理执行待执行的事件,event队列;3.阻塞GUI渲染
c. 定时器触发引擎 -- 1. 异步定时器处理与执行,setTimeout&setInterval;2.接收JS引擎分配的定时器任务,并计数;3.处理完成后交与事件触发引擎
d. 异步HTTP请求线程【I/O】 -- 1. 异步执行请求类处理:Promise/ajax等;2.接收js引擎分配异步HTTP请求;3. 监听回调,交给事件触发线程触发
e. 事件触发引擎 -- 1. 接收来源:定时器、异步、用户操作;2. 将回调过来的事件依次进入到任务队列,还给JS引擎
(Chrome独有:3d加速)
2. EVENT-LOOP
a. 执行栈
- JS单线程语言,单步执行
function run() {
func1()
}
function func1() {
func2()
}
function func2() {
throw new Error("please check your call stack");
}
run();
js执行原理(高级)
Memory Heap(储存堆,分配内存)
Call Stack(执行栈,执行回调)
webAPI
* DOM
* AJAX
* setTimeout
b. 面试题
- JS堆栈的执行顺序与堆栈溢出 => 性能优化
// 堆栈溢出 -> 死循环
function func() {
func();
}
func()
任务分为宏任务和微任务
宏任务(macro): script[script标签] setTimeout setInterval I/O
微任务(micro): new Promise().then()
宏任务优先级大于微任务;
先执行宏任务,宏任务执行完毕后,判断有没有微任务,有微任务则执行微任务,无微任务则执行宏任务(有微则微,无微则宏)
任务分为同步任务和异步任务
判断当前任务是同步还是异步,是同步直接进入主线程;是异步则进入event table(把所有的异步任务进行声明和聚集),主线程执行完毕后,再去调event queue。
- 执行顺序题
setTimeout(() => { // 异步宏任务
console.log('1');
})
Promise.resolve(1).then(() => { // 微任务
console.log('2')
}
console.log('3'); // 同步宏任务
// 执行顺序 321
// 追问:思考
辅助理解事件队列(event queue)
https://blog.csdn.net/weixin_30871701/article/details/97270307
promise
a. 理论
// 1.异步定时器
setTimeout(() => {
console.log('1');
}, 2000)
// 2. 异步请求
request.onreadystatechange = () => {
if(request.readyState === 4) {
const _status = resquest.status;
if(_status === 200) {
const _res = resquest.responseText;
return success(_res);
} else {
return fall(_status);
}
}
}
// 3. 延时后再请求
setTimeout(() => {
console.log('1');
request.onreadystatechange = () => {
if(request.readyState === 4) {
const _status = resquest.status;
if(_status === 200) {
const _res = resquest.responseText;
return success(_res);
} else {
return fall(_status);
}
}
}
},2000)
// 4. 再延时再请求? -- 回调地狱
setTimeout(() => {
console.log('1');
request.onreadystatechange = () => {
if(request.readyState === 4) {
const _status = resquest.status;
if(_status === 200) {
const _res = resquest.responseText;
setTimeout(() => {
console.log('1');
request.onreadystatechange = () => {
if(request.readyState === 4) {
const _status = resquest.status;
if(_status === 200) {
const _res = resquest.responseText;
return success(_res);
} else {
return fall(_status);
}
}
}
},2000)
return success(_res);
} else {
return fall(_status);
}
}
}
},2000)
// 5. promise的出现,拯救了回调导致的无穷嵌套
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("OK");
}, 1000)
}).then(r => {
console.log("then:" + r);
}).catch(err => {
console.log("catch:" + err);
})
// 6. 多个异步顺序执行 => 链式调用
function wait500(input) {
return new Promise((reslove, reject) => {
resolve(input + 500)
}, 500)
}
function wait1000(input) {
return new Promise((reslove, reject) => {
resolve(input + 1000)
}, 1000)
}
const p = new Promise((reslove, reject) => {
resolve(1)
})
p.then(wait500).then(wait1000).then(wait500).then(wait1000).then(result => {
console.log('end' + result);
})
// 7. Promise.all() 具有全部执行完成后再操作的作用
Promise.all([wait500, wait1000]).then(results => { // 数组队列里面的请求全部执行完毕后即可执行打印
console.log('all end' + results); // results 返回一个数组,数组元素是function(数组队列中的function)
})
// 8. Promise.race() 一旦有一个执行完成的,立刻操作
Promise.race([wait500, wait1000]).then(results => { // 数组队列里面只要有一个请求执行完毕后就可执行打印
console.log('race end' + results); // results // 返回一个function
})
// all和race返回值问题
b. 面试题
描述promise框架(promise规范)
- 1.promise有哪些状态?对应值有哪些? - pending、fulfilled、rejected
- 2.new Promise 执行器executor(), 执行器接收参数是? - reslove,reject
- 3.promise状态的流转(类状态机)?promise的默认状态是?- 默认pending,要么pending->fulfilled,要么pending -> rejected;
- 4.promise,value保存成功状态的枚举? - undefined/thenable/promise
- 5.promise,reason失败状态值?- reason保存失败
描述promise接口
- 6.promise一定会有then,then接收来源?- 两个回调 onFulfilled(value) + onRejected(reason)
// 三个状态PENDING、FULFILLED、REJECTED
const PENDING = 'PENDING';
const FULFILLED= 'FULFILLED';
const REJECTED= 'REJECTED';
// 同步
class Promise { // 搭建一个Promise的类
constructar(executor) { // 构造器
// 默认状态值:PENDING
this.status = PENDING;
// 成功状态的值
this.value = undefined;
// 失败状态的值
this.reason = undefined;
// 成功状态的回调
let resolve = value => {
if(this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
}
}
// 失败状态的回调
let rejected = reason => {
if(this.reason === PENDING) {
this.status = REJECTED;
this.reason = reason;
}
}
}
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);
}
}
}
const promise = new Promise((resolve, reject) => {
resolve('成功');
}).then(data => {
// 从value来
}).catch(error => {
// 从reject来
})
// 异步:区别- 依次调用【需要event queue】
class Promise { // 搭建一个Promise的类
constructar(executor) { // 构造器
// 默认状态值:PENDING
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 => fun())
}
}
// 失败状态的回调
let rejected = reason => {
if(this.reason === PENDING) {
this.status = REJECTED;
this.reason = reason;
// 依次调用失败函数的执行
(this.onRejectedCallbacks || []).forEach(fn => fun())
}
}
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);
})
}
}
}
const promise = new Promise((resolve, reject) => {
resolve('成功');
}).then(data => {
// 从value来
}).catch(error => {
// 从reject来
})
// 启示:同步 => 异步
// 顺序和空间的关系