编辑代码

// 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

// 3Promise有哪些状态,何时变化
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 doclass 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));
        })
    }
}