当我们需要给予调用者一个承诺:待会儿我会给你回调数据时,就可以创建一个Promise的对象;
在通过new创建Promise对象时 ,我们需要传入一个回调函数,我们称之为executor,这个回调函数会被立即执行,并且给传入另外两个回调函数resolve、reject;
- 当我们调用resolve回调函数时,会执行Promise对象的then方法传入的回调函数;
- 当我们调用reject回调函数时 ,会执行Promise对象的catch方法传入的回调函数;
基本用法:
Promise 内传入的这个函数被称为executor, resolve : 回调函数,在成功时回调resolve函数 reject : 回调函数,在成功时回调 reject 函数
const promise = new Promise((resolve, reject) => {
// 执行传入的回调函数
resolve()
// reject()
})
promise.then(() => {})
promise.catch(() => {})
等价于:
new Promise((resolve, reject) => {
// 执行传入的回调函数
resolve()
// reject()
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
状态值
pending(待定)
初始状态,当执行executor中的代码,处于该状态
fulfilled(成功)
操作成功,执行resolve函数处于该状态
rejected(失败)
操作失败,执行reject函数处于该状态
状态值不可逆,只能由 pending -> fulfilled/resolved pending-> rejected
fulfilled 和resolved 是同一个东西
resolve(参数)
参数值:
- 普通对象或者数据 resolv会将状态由 pending -> fulfilled 2.传入 Promise 对象 如果给resolve传入一个Promise对象,那么这个状态会由传入的Promise决定, 相当于状态移交 3.传入一个对象,且对象有实现then方法(该对象实现了thenable) 那么也会执行then方法,并且该then方法的结果决定后续状态
resolve传值三种情况:
// 不使用的时候先注掉
// const p1 = new Promise((resolve, reject) => {
// reject("传入Promise对象")
// })
const obj = {
then: function (resolve, reject) {
resolve("传入thenable对象")
}
}
new Promise((resolve, reject) => {
// 执行传入的回调函数
// 情况一:传入普通值 字符串
// resolve("123")
// 情况二:resolve传入一个Promise
// resolve(p1)
// 情况三:传入thenable对象
resolve(obj)
}).then(res => {
console.log("成功回调", res);
}).catch(err => {
console.log("失败回调", err);
})
在些在后续实现Promise 时都要考虑
resolve返回值是一个Promise
executor
在创建Promise 传入的一个回调函数,回调函数会被立即执行,并传入两个参数:
new Promise((resolve, reject) => {
resolve("executor代码")
})
then
the方法是放在Promise原型上的Promise.prototype.then() 接收两个参数:
- fulfilled的回调函数:成功回调
- rejected 的回调函数:失败回调
then方法可以被回调多次,且在成功状态下时,会全部回调
then返回值是一个Promise,如果返回的是一个普通值,这个普通值会作为一个新的Promise传递
new Promise((resolve, reject) => {
resolve("123")
}).then(res => {
console.log("成功回调", res);
}, err => {
console.log("err", err);
})
finally
finally没有参数,无论成功还是失败,最后都会走到 finally
new Promise((resolve, reject) => {
resolve("123")
}).then(res => {
console.log("成功回调", res);
}, err => {
console.log("err", err);
}).then(res => {
console.log("455454");
}).finally(() => {
console.log("finally");
})
Promise.resolve()
类方法 resolve 内的参数和executor内的参数状态一致
const promise = Promise.resolve({ name: '123' })
// 等价于
const promise1 = new Promise((resolve, reject) => {
resolve({ name: "123" })
})
将内部参数转成prmise返回回去
Promise.reject()
const promise = Promise.reject("rejected msg")
// 等价于
const promise1 = new Promise((resolve, reject) => {
reject("rejected msg")
})
内部操作
// reject内部不管传什么值,直接走catch
const promise = Promise.reject(new Promise(() => { }))
promise.then(res => {
console.log("res", res);
}).catch(err => {
console.log("err", err); // err Promise { <pending> }
})
Promise.all()
在内部所有的Promise都变成fulfilled时,再拿到结果 但是在拿到结果之前,有一个结果变成rejected,那整个promise都会变成rejected
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p1-reolve-2s")
}, 2000)
})
const p2 = new Promise((resolve, reject) => {
resolve("p2--resolve")
// reject("p2-reject")
})
Promise.all(['a', 'b', p1, p2, 'c']).then(res => console.log("res-all", res))
// res-all [ 'a', 'b', 'p1-reolve-2s', 'p2--resolve', 'c' ]
Promise.allSettled()
all的缺点是:当状态有一个是rejected,那promise整体都会变成rejected
等于,获取不到内部其他结果。
ES11(ES2020) 中添加了allSettled
,这个方法会在所有Promise都有结果(settled),无论状态是pending还是rejected,都会有结果;而且这个Promise结果一定是fulfilled的
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p1-reolve-2s")
}, 2000)
})
const p2 = new Promise((resolve, reject) => {
reject("p2-reject")
})
Promise.allSettled(['a', 'b', p1, p2, 'c']).then(res => console.log(res))
/*
[
{ status: 'fulfilled', value: 'a' },
{ status: 'fulfilled', value: 'b' },
{ status: 'fulfilled', value: 'p1-reolve-2s' },
{ status: 'rejected', reason: 'p2-reject' },
{ status: 'fulfilled', value: 'c' }
]
*/
可以看到打印结果:
成功的状态为fulfilled
,返回value
为 传入的值
失败的状态为rejected
,返回 reason
为 传入的值
allSettled
的结果是一个数组,数组内存放着每一个Promise结果,并对应每一个对象,对象内部包含 当前 status状态值、value 运行返回结果(成功是value),reason(失败原因)
Promise.race()
只要有一个fulfilled,直接返回正常,或者是有一个异常 直接 reject
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p1-reolve-2s")
}, 2000)
})
const p2 = new Promise((resolve, reject) => {
reject("p2-reject")
})
Promise.race([p1, p2]).then(res => {
console.log("res", res)
}).catch(err => {
console.log("err", err); // err p2-reject
})
Promise.any()
any() 至少要等到一个resolve结果 返回 如果没有resolve,才会执行catch 会给一个合计结果
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p1-reolve-2s")
}, 2000)
})
const p2 = new Promise((resolve, reject) => {
reject("p2-reject")
})
Promise.any([p1, p2]).then(res => {
console.log("res", res) // res p1-reolve-2s
}).catch(err => {
console.log("err", err);
Promise源码
const PENDING = "PENGING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
class MyPromise {
constructor(executor) {
try {
executor(this.resolve, this.reject)
} catch (err) {
this.reject(err)
}
}
// 设置promise初始状态
status = PENDING;
// 成功后的值
value = undefined
// 失败后的值
reason = undefined
// 成功回调
successCallback = []
// 失败回调
failCallback = []
resolve = value => {
// 如果状态不是等待,阻止程序向下执行
if (this.status !== PENDING) return;
// 将状态改为成功
this.status = FULFILLED
// 保存成功后的原因
this.value = value
// 判断成功回调是否存在,如果存在,调用
// this.successCallback && this.successCallback(this.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(this.reason)
// 处理promise多个then方法调用情况
while (this.failCallback.length) this.failCallback.shift()()
}
then(successCallback, failCallback) {
successCallback = successCallback || (value => value);
failCallback = failCallback || (reason => { throw reason });
// then的链式调用,需要返回一个promise对象
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = successCallback(this.value)
// 将上一个then的返回值,传递给下一个then
// resolve(x)
// 这里返回的值会有多种:普通值、promise对象、实现thenable的对象
// 1.如果是普通值,直接调用resolve
// 2.如果是promise对象,查看promise对象返回的结果
// 再根据promise返回的结果决定调用resolve 还是reject
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
}, 0)
} else {
// promise是立即执行,当在请求接口或者延迟执行时会进入等待状态
// 所以不确认是成功还是失败
// 等待 将成功回调或失败回调存储起来
this.successCallback.push(() => {
// successCallback()
setTimeout(() => {
try {
let x = successCallback && successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
}, 0)
})
this.failCallback.push(() => {
// failCallback()
setTimeout(() => {
try {
let x = failCallback && failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
}, 0)
})
}
});
return promise2
}
finally(callback) {
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value)
}, reason => {
return MyPromise.resolve(callback()).then(() => { throw reason })
})
}
catch(failCallback) {
return this.then(undefined, failCallback)
}
static all(array) {
let result = []
let index = 0
return new MyPromise((resolve, reject) => {
function addData(key, value) {
result[key] = value
index++
// 等所有异步操作完成后,才可以调用resolve方法
if (index === array.length) {
resolve(result)
}
}
for (let i = 0; i < array.length; i++) {
let current = array[i]
if (current instanceof MyPromise) {
// promise对象
current.then(value => addData(i, value), reason => reject(reason))
} else {
// 普通值
addData(i, array[i])
}
}
})
}
static resolve(value) {
if (value instanceof MyPromise) return value
return new MyPromise(resolve => resolve(value))
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
// 判断x是否为promise实例
if (x instanceof MyPromise) {
// promise对象
// x.then(value => resolve(value), reason => reject(reason))
// 可以简化为下方代码
x.then(resolve, reject)
} else {
// 普通值
resolve(x)
}
}
module.exports = MyPromise