// 状态常量
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