Promise
-
promise是一个函数,new 对象使用,返回resolve和reject两个成功、失败的回调函数
new Promise((resolve,reject)=>{ console.log(1) resolve(2) console.log(3) }).then((res=>{ console.log(res) }).catch(()=>{ console.log('err') }) // 打印 1 3 2 -
在本轮事件循环运行完成之前,回调函数是不会执行的
-
及时异步操作已经完成,在这之后通过then添加的回调函数也会被调用
-
通过多次调用then可以添加多个回调函数,他们会按照插入顺序链式调用,都是一起加入微任务队列
Promise.resolve() .then(() => { console.log(1); setTimeout(()=>console.log(4)) }) Promise.resolve() .then(() => console.log(2)) .then(() => console.log(3)); // 打印 1 2 3 4const transformData = composeAsync(fn1,fn2,fn3) const result = transformData(data) // 实现composeAsync,其中fn1,fn2,fn3是返回promise的函数,参数依次接受前面返回值,fn1的参数是data function composeAsync(...args){ return data => args.reduce((p,c)=>{ return p.then(c) },Promise.resolve(data)) } // ==> const asyncFn = (p,c)=>p.then(c) const composeAsync = (...args) => data => args.reduce(asyncFn,Promise.resolve(data)) -
一旦遇到失败,会顺着promise寻找下一个onRejected失败回调或者.catch()指定的回调函数
-
当promise被拒绝时,会派发到全局事件,如果有reject处理事件是 rejectionhandled ,没有reject处理事件是 unhandledrejection
window.addEventListener("unhandledrejection", event => { /* 你可以在这里添加一些代码,以便检查 event.promise 中的 promise 和 event.reason 中的 rejection 原因 */ event.preventDefault(); // 默认操作一般会包含把错误打印到控制台,Node 就是如此的 }, false); -
Promise.resolve 和 Promies.reject 是手动创建resolve和reject的promise方法
-
Promise.all 和 Promise.race 中all是都完成才返回,如果有一个失败就全部终止失败退出,race是任意一个完成就返回
Promise 实现
// 特性:
// - 函数 返回自身,链式调用
// - 构造函数是宏队列,then后是微队列,已敲定后不能再改
// - 1、静态方法:all,allSettled,any,race,resolve,reject
// - all 都是成功返回数组给then,或者有一个失败就都终止且返回错误给catch
// - allSettled 都已敲定状态,有成功有失败,数组返回给then
// - any 任意一个成功就终止,返回给then
// - race 任意一个已敲定就终止, 成功返回给then,失败返回给catch
// - 2、实例方法 then,catch,finally
function Promise(callback) {
if (!this instanceof Promise) {
return console.error('must call by new Promise')
}
if (typeof callback != 'function') {
return console.error('need callback function')
}
this.status = 'PENDING'
const resolve = (value) => {
if (this.status != 'PENDING') return
this.status = 'FULFILLED'
this.value = value
setTimeout(() => {
this.resolveFn?.(value)
})
}
const reject = (reason) => {
if (this.status != 'PENDING') return
this.status = 'REJECTED'
this.reason = reason
setTimeout(() => {
this.rejectFn?.(reason)
})
}
try {
callback(resolve, reject)
} catch (e) {
reject(e)
}
}
Promise.prototype.then = function (resolve, reject) {
return new Promise((nextResolve, nextReject) => {
resolve = resolve || Promise.resolve
reject = reject || Promise.reject
nextResolve = nextResolve || Promise.resolve
nextReject = nextReject || Promise.reject
const handler = (result) => {
if (result instanceof Promise) {
if (result.status == 'FULFILLED') {
nextResolve(result.value)
}
if (result.status == 'REJECTED') {
nextReject(result.reason)
}
}
nextResolve(result)
}
this.resolveFn = (value) => {
const result = resolve(value)
handler(result)
}
this.rejectFn = (reason) => {
const result = reject(reason)
handler(result)
}
})
}
Promise.prototype.catch = function (reject) {
return this.then(null, reject)
}
Promise.prototype.finally = function (fn) {
const newFn = () => fn()
return this.then(newFn, newFn)
}
Promise.all = function (array) {
return new Promise((resolve, reject) => {
const obj = Object.create(null)
array.forEach((it, index) => {
it.then(value => {
obj[index] = value
if (Object.keys(obj).length == array.length) {
resolve(Object.values(obj))
}
}, reason => {
reject(reason)
})
})
})
}
Promise.allSettled = function (array) {
return new Promise((resolve, reject) => {
const obj = Object.create(null)
array.forEach((it, index) => {
it.then(value => {
obj[index] = value
if (Object.keys(obj).length == array.length) {
resolve(Object.values(obj))
}
}, reason => {
obj[index] = reason
if (Object.keys(obj).length == array.length) {
reject(Object.values(obj))
}
})
})
})
}
Promise.any = function (array) {
return new Promise((resolve) => {
array.forEach((it) => {
it.then(value => {
resolve(value)
})
})
})
}
Promise.race = function (array) {
return new Promise((resolve, reject) => {
array.forEach((it, index) => {
it.then(value => {
resolve(value)
}, reason => {
reject(reason)
})
})
})
}
Promise.resolve = function (value) {
return new Promise((resolve) => {
resolve(value)
})
}
Promise.reject = function (reason) {
return new Promise((_, reject) => {
reject(reason)
})
}