1.请描述Event loop(事件循环)的机制。
JS是单线程的,异步需要基于毁掉来实现,event loop 就是异步回调的实现原理。
同步代码,一行一行放在Call Stack执行,遇到异步任务,标记一下让其他线程去处理(定时,网络请求等),其他线程处理完毕就放到callback Queue, 如果Call stack清空(即同步代码执行完),开始执行当前的微任务和微任务引发的微任务,执行完毕微任务队列,然后尝试进行DOM渲染,渲染结束,Event loop开始工作,轮询查找Callback Queue, 如果有则移动到Call Stack执行,然后继续重复上述步骤(永动机一样)。
2.什么是宏任务和微任务,两者有什么区别?
宏任务: setTimeout、setInterval、Ajax、DOM事件
微任务 :Promise、 async/await、
微任务执行时机比宏任务要早,微任务在DOM渲染前触发,宏任务在DOM渲染后出触发。微任务是ES6语法规定,宏任务是由浏览器规定的
3.Promise 有哪三种状态?如何变化?
三种状态:pending\resolved\rejected
pending ->resolved或pending -> rejected,变化不可逆。
resolved 会触发then回调,rejected会触发catch回调,只要回调里面没有报错,无论是then或catch返回的都是resolved状态,报错时会返回rejected状态。
4.async/await Promise的关系
执行async函数,返回的是一个Promise对象;await相当于Promise的then; try...catch可捕获异常,代替了Promise的catch。await后边的内容都可以当作异步回调的内容。
5.手写Promise
- 初始化&异步调用
- then链式调用
- API、resolve、 reject 、all、 race、
js
class MyPromise {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.onResolveCallbacks = [];
this.onRejectCallbacks = [];
const resolve = (value) => {
if (this.state === "pending") {
this.state = "fulfilled";
this.value = value;
this.onResolveCallbacks.forEach((callback) => callback(this.value));
}
};
const reject = (reason) => {
if (this.state === "pending") {
this.state = "rejected";
this.value = reason;
this.onRejectCallbacks.forEach((callback) => callback(this.value));
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onResolve, onReject) {
return new MyPromise((resolve, reject) => {
if (this.state === "fulfilled") {
try {
const result = onResolve(this.value);
resolve(result);
} catch (error) {
reject(error);
}
} else if (this.state === "rejected") {
try {
const result = onReject(this.value);
resolve(result);
} catch (error) {
reject(error);
}
} else {
this.onResolveCallbacks.push((value) => {
try {
const result = onResolve(value);
resolve(result);
} catch (error) {
reject(error);
}
});
this.onRejectCallbacks.push((reason) => {
try {
const result = onReject(reason);
resolve(result);
} catch (error) {
reject(error);
}
});
}
});
}
catch(onReject) {
return this.then(null, onReject);
}
}