function MyPromise(func) {
this.status = 'pending' // resolve, reject
this.thenFuncs = []
this.catchFuncs = []
this.value = undefined
func(MyPromise.resolve.bind(this), MyPromise.reject.bind(this))
}
MyPromise.resolve = function(result) {
this.value = result
this.status = 'resolve'
this.thenFuncs.forEach(func => func(result))
}
MyPromise.reject = function(error) {
this.value = error
this.status = 'reject'
this.catchFuncs.forEach(func => func(error))
}
MyPromise.prototype.then = function(thenFunc) {
if (this.status === 'resolve') {
thenFunc(this.value)
} else {
this.thenFuncs.push(thenFunc)
}
return this
}
MyPromise.prototype.catch = function(catchFunc) {
if (this.status === 'reject') {
catchFunc(this.value)
} else {
this.catchFuncs.push(catchFunc)
}
return this
}
// ----- start ----------
new MyPromise((resolve, reject) => {
if (false) {
setTimeout(() => {
resolve(123)
}, 3000)
} else {
reject('error')
}
}).then(result => {
console.log(result)
}).then(result => {
console.log(result)
}).then(result => {
console.log(result)
}).catch(error => {
console.log(error)
}).catch(error => {
console.log(error)
}).catch(error => {
console.log(error)
})
独自のカプセル化された Promise を使用すると、新しい Promise で渡されたメソッドが非同期メソッドではない場合、その .then が最初に実行され、元の Promise と多少矛盾していることがわかります。
実は、オリジナルの Promise がマイクロタスクにタスクを追加しているためです。
windowのqueueMicrotask APIを使用します
queueMicrotask(() => {
/* 微任务中将运行的代码 */
});