SOURCE

// 状态常量
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

// 微任务的实现
const { instanceQueve, timerFunc } = (() => {
    let instanceQueve = []
    let counter = 1
    const observer = new MutationObserver(() => {
        const tempQueve = instanceQueve.slice().reverse()
        let len = tempQueve.length
        while(len--) {
            const instance = tempQueve[len]
            if(instance.status == FULFILLED) {
                instance.onFulfilled.forEach(cb => cb())
            } else {
                instance.onRejected.forEach(cb => cb())
            }
            instanceQueve.shift()
        }
    })
    const textNode = document.createTextNode(String(counter))
    observer.observe(textNode, {
        characterData: true
    })
    const timerFunc = () => {
        counter = (counter + 1) % 2
        textNode.data = String(counter)
    }

    return {
        instanceQueve,
        timerFunc
    }
})()

// 决定使用那种任务
// 先尝试使用 微任务 不支持则降级到 宏任务
// 参考 vue 源码 nextTick 的实现
function decisionTask() {
    // https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver
    // https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver/observe
    // https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserverInit
    if (
        MutationObserver !== 'undefined' || (
        MutationObserver.toString() === '[object MutationObserverConstructor]')
    ) {
        timerFunc()
        instanceQueve.push(this)
        return
    } 
    
    setTimeout(() => {
        // 触发回调
        if(this.status == FULFILLED) {
            this.onFulfilled.forEach(cb => cb())
        } else {
            this.onRejected.forEach(cb => cb())
        }
    }, 0)
}

// Promise 类
function LPromise(executor) {
    this.status = PENDING   // 当前状态
    this.value = undefined  // 当前值
    this.onFulfilled = []    // 缓存成功回调
    this.onRejected = []     // 缓存失败回调
    this.resolveFn = body => {  // resolve 函数
        // 只有当当前状态为 pedding 才触发
        if (this.status !== PENDING) return

        this.status = FULFILLED
        this.value = body
        
        decisionTask.call(this)
    }
    this.rejectFn = error => {  // reject 函数
        if (this.status !== PENDING) return

        this.status = REJECTED
        this.value = error
        
        decisionTask.call(this)
    }

    // 立即执行 executor 函数
    // try catch 是为了防止 executor 里面内容发生异常
    try {
        executor(this.resolveFn, this.rejectFn)
    } catch (e) {
        this.rejectFn(e)
    }
}

// then 方法
// 接收一个成功回调(onFulfilled) 一个失败回调(onRejected)
LPromise.prototype.then = function (onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => { }
    onRejected = typeof onRejected === 'function' ? onRejected : () => { }

    // 链式调用
    const _promise = new LPromise((resolve, reject) => {
        // 缓存用户传进来的 onFulfilled、onRejected 回调函数
        // 当用户主动触发 resolve/reject 的时候再调用
        this.onFulfilled.push(() => {
            // 将当前回调返回的结果
            // 返回到下一个 Promise 的成功回调中
            try {
                const result = onFulfilled(this.value)
                resolve(result)
            } catch (e) {
                reject(e)
            }

        })

        this.onRejected.push(() => {
            // 将当前回调返回的结果
            // 返回到下一个 Promise 的成功回调中
            try {
                const result = onRejected(this.value)
                resolve(this.value)
            } catch (e) {
                reject(e)
            }
        })
    })

    return _promise
}

// 捕获错误
// 接收一个失败回调(onRejected)
LPromise.prototype.catch = function (onRejected) {
    this.then(null, onRejected)
}

LPromise.resolve = function (value) {
    return new LPromise((resolve, reject) => {
        resolve(value)
    })
}

LPromise.reject = function (value) {
    return new LPromise((resolve, reject) => {
        reject(value)
    })
}

console.log('script start')

LPromise.resolve(1).then(res => console.log(res)).then(res => console.log(res))
p = LPromise.resolve(2)
p.then(res => console.log(res))
p.then(res => console.log(res))
const lp1 = new LPromise((resolve, reject) => {
    a
})

lp1.then(body => { }, error => {
    console.log(error, 'err')
})

const lp2 = new LPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('sleep 1000ms')
    }, 1000)
})

lp2.then(body => {
    console.log(body)
    return 1
}, null)

const lp3 = new LPromise((resolve, reject) => {
    setTimeout(() => {
        reject('失败了')
    }, 1000)
})

lp3.then()
lp3.catch(fail => console.log(fail, ' lp3 err'))

const lp4 = new LPromise((resolve, reject) => {
    setTimeout(() => {
        resolve(1)
    }, 1)
})

lp4
    .then(body => {
        console.log(body)
        return '嘻哈'
    }, null)
    .then(body => {
        console.log(body)
        return 1
    }, null)

const lp5 = new LPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('测试 then 里面抛出异常')
    }, 10)
})

lp5
    .then(body => {
        console.log(body)
        console.log(b)

        return '嘻哈'
    }, null)
    .then(null, error => {
        console.log('上一个 then 里面抛出了异常,被我接收到了哦!!')
        console.log(error)
    })

// 暂时没意义 因为我们使用宏任务模拟实现的
LPromise.resolve(setTimeout(() => console.log('setTimeout'), 1000))
    .then(body => console.log(body, 'Promise.resolve'))
LPromise.reject(setTimeout(() => console.log('setTimeout'), 1000))
    .then(null, body => console.log(body, 'Promise.reject'))

console.log('script end')

// bind 在修改原函数的情况下
// 多次绑定无效
// 只会取第一次的值
// Function.prototype.mBind = function (obj) {
//     obj.fn = this
//     return () => {
//         obj.fn()
//         delete obj.fn
//     }
// }

// function a() {
//     console.log(this.a)
// }
// var obj = {a: 1}
// a.mBind(obj).mBind({b: 2})
// console.log(obj)
// console.log(a.mBind(obj).mBind({b: 2}))
console 命令行工具 X clear

                    
>
console