// 1、讲一下事件循环(Event Loop)
js是单线程语言,放了防止主线程阻塞,就产生了同步任务和异步任务,
简单来说不耗时的就是同步任务,耗时的就是异步任务,为了 协调同步任务和异步任务的执行顺序,
就出现了事件循环的概念。
流程大概如下:
js代码执行 -> 同步任务还是异步任务
-> 同步任务 -> 压栈(Call Stack)执行 -> 执行完成出栈直到没有同步任务
-> 异步任务 -> 进入异步处理模块 -> 如果是遇到微任务如Promise,则把其对应的then回调看准时机注册到micro task queue,如果是宏任务(Web APIs),则时间到注册到任务队列中(Callback Queue)
主任务执行完成后,没有同步任务后,会尝试进行DOM渲染,然后就开始Event Loop,一直读取Callback Queue,读取的过程是先微任务再宏任务。
具体文字描述为:
1、先执行同步任务,遇到异步任务则交给异步处理模块处理
2、当同步任务全部执行完毕,也就是Call Stack为空,执行所有微任务
3、微任务队列执行完,会尝试进行DOM渲染
4、DOM渲染完成后,就查看Callback Queue回调队列,也就是宏任务,如果有,就执行一个宏任务,之后1234反复执行
假想图:
1、Call Stack (任务执行区域) -> 遇微入微处理,遇宏入Web APIs处理 -> 时机已到分别注册到Micro Queue和Callback Queue
2、Micro Queue (微任务队列)
3、DOM渲染
4、Callback Queue (宏任务队列)
5、Event Loop(反复查看是有任务,之后又会进入12345的流程)
// 2、什么是宏任务和微任务以及它们的区别
宏任务:setTimeput、setInterval、setImmediate、Ajax、DOM事件、I/O、UI render
微任务:Promise、process.nextTick、Object.observer、MutationObserver
// 3、Promise有哪些状态,何时变化
resolved(fullfilled),rejected,pending
有两个需要注意的点:
then正常返回resolved状态,报错或抛出错误返回rejected
catch正常返回resolved状态,报错或抛出错误返回rejected
Promise.resolve()
.then(() => console.log(1))
.catch(() => console.log(2))
.then(() => console.log(3)); // 1 3
Promise.resolve()
.then(() => { throw new Error('aa') })
.then(() => console.log('then'))
.catch(() => console.log('catch')); // catch
Promise.resolve()
.then(() => { throw new Error('aa') })
.catch(() => console.log('catch'))
.then(() => console.log('then')); // catch then
Promise.resolve()
.then(() => { throw new Error('aa') })
.catch(() => console.log('catch'))
.catch(() => console.log('catch')); // catch
const p = new Promise((resolve, reject) => {
});
4、手写Promise(to do)
class MyPromise {
status = 'pending'; // 只有三个状态pending、fullfiled、rejected
value = undefined; // 成功的值
reason = undefined; // 失败的值
resolveCallbacks = []; // 要处理的then回调,只在pending状态才会存入
reasonCallbacks = []; // 要处理的catch回调
constructor (callback) {
const resolveFn = (value) => {
if (this.status !== 'pending') return; // 只有pending才可以继续改状态,其它已改变的状态不能再改
this.status = 'fullfiled';
this.value = value;
this.resolveCallbacks.forEach((fn) => {
fn(this.value);
});
}
const rejectFn = (reason) => {
if (this.status !== 'pending') return;
this.status = 'rejected';
this.reason = reason;
this.reasonCallbacks.forEach((fn) => {
fn(this.reason)
})
}
callback(resolveFn, rejectFn);
}
then(fn) {
return new MyPromise((resolve, reject) => {
// 三种状态()
})
}
catch(fn) {
return new Promise((resolve, reject) => {
reject(fn(this.reason));
})
}
}