web浏览器中有js线程,异步调用线程
promise中的then方法实际上是创建了新的proimse对象
macrotask(宏任务): setTimeout,setInterval
microtask(微任务): promise的回调,process.nextTick,mutationObserver
手写Promise源码
// 1.new Promise立即执行并且可以调用resolve和reject, resolve和reject会保存值,传递给then方法使用
// 2.三种状态,Pending,Fulfilled和 Rejected 状态不可逆
// 3.then 方法接受成功和失败的回调函数
// 4. promise中的then方法可以多次调用
// const promiseB = new Promise((resolve, reject) => {
// resolve(1)
// })
// promiseB.then(data => {
// console.log(data)
// })
// promiseB.then(data => {
// console.log(data)
// })
// promiseB.then(data => {
// console.log(data)
// })
// 5. then是链式调用的,then方法的返回值会传递给下一个then 方法,返回值可能是promise对象
// 如果then方法返回当前promise的话提示报错typeError
// 6. new Promise处理异常,new Promise执行的时候执行异常,成功调用的时候异常, 处理失败的时候异常
// 7. then中的参数是可选的可以不传递参数
// new Promise((resolve , reject) => resolve(1)).then().then().then(value => console.log(value))
// 8. Promise.all的实现 根据数组的顺序返回解析过后的值,有一个reject就返回reject
// 9. Promise.resolve 相当于是个promise对象直接调用then方法
// 实现 : 如果是promise对象就直接返回promise, 如果是普通值就创建promise返回
// 9. finally中回调函数可以直接执行,return(可以return promise对象)之后,可以使用then方法接受finally中的return
const PENDING = 'pending'
const FUFLILLED = 'fuflilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) {
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
// 定义初始状态
status = PENDING
// 接受resolve的初始值
value = undefined
// 接收失败的初始值
reason = undefined
// then 成功回调
successCallback = []
// then 失败回调
failCallback = []
resolve = (value) => {
// 过程不可逆
if (this.status !== PENDING) return
// 修改状态
this.status = FUFLILLED
// 保存值
this.value = value
// 处理异步
// this.successCallback && this.successCallback(value)
while (this.successCallback.length) this.successCallback.shift()()
}
reject = (reason) => {
// 过程不可逆
if (this.status !== PENDING) return
// 修改状态
this.status = REJECTED
// 保存值
this.reason = reason
// 处理异步
// this.failCallback && this.failCallback(reason)
while (this.failCallback.length) this.failCallback.shift()()
}
then (successCallback, failCallback) {
// 处理then中参数是可选的,将参数传递到下一个then中
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => { throw reason }
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FUFLILLED) {
setTimeout(() => {
try {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
} else {
// 处理异步 保存成功和失败回调
this.successCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
this.failCallback.push(() => {
setTimeout(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
}
})
return promise2
}
finally (callback) {
// 获取当前的promise的状态然后执行回调函数
return this.then(value => {
// 转换成promise对象,先执行callback然后再执行then
return MyPromise.resolve(callback(value)).then(() => value)
}, reason => {
return MyPromise.resolve(callback(value)).then(() => { throw reason })
})
}
catch (failCallback) {
// 获取当前的promise的状态然后执行回调函数,不过这里只传递失败的回调
return this.then(undefined, failCallback)
}
static all (arr) {
let result = []
// 解决异步调用的问题
let index = 0
return new MyPromise((resolve, reject) => {
function addData (key, value) {
result[key] = value
index++
if (index === result.length) {
resolve(result)
}
}
for (let i = 0;i < arr.length;i++) {
let current = arr[i]
if (current instanceof MyPromise) {
// 是promise对象
current.then(value => {
addData(i, value)
}, reason => reject(reason))
} else {
// 普通值
addData(i, current)
}
}
})
}
static resolve (value) {
if (value instanceof MyPromise) return value
return new MyPromise(resolve => resolve(value))
}
}
// 解析promise
// 先判断是否是promise对象还是普通值,如果是普通值就直接resolve传递下去,如果是promise对象判断promise的状态之后,再将值传递下去
function resolvePromise (promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Uncaught (in promise) ReferenceError: Cannot access promise before initialization'))
}
if (x instanceof MyPromise) {
// promise对象
x.then(resolve, reject)
} else {
// 普通值
resolve(x)
}
}
module.exports = {
MyPromise
}