promise 定义
Promise:promise 是⼀个拥有 then ⽅法的对象或函数,其⾏为符合本规范。 具有 then ⽅法(thenable):是⼀个定义了 then ⽅法的对象或函数; 值(value):指任何 JavaScript 的合法值(包括 undefined , thenable 和 promise); 异常(exception):是使⽤ throw 语句抛出的⼀个值。 原因(reason):表示⼀个 promise 的拒绝原因
.如果onFulfilled是一个函数,且有返回值,则返回值可以继续传递给后续的then
.如果onFulfilled是一个函数,但没有返回值(相当于return undefined),则后续then中的入参为undefined
.如果onFulfilled不是函数,则忽略当前then,将参数直接传递给后续的then
如果 x 有 then ⽅法且看上去像⼀个 Promise ,解决程序即尝试使 promise 接受 x 的状态;否则其 ⽤ x 的值来执⾏ promise 。 如果 promise 和 x 指向同⼀对象,以 TypeError 为据因拒绝执⾏ promise 如果 x 为 promise 如果 x 处于等待态, promise 需保持为等待态直⾄ x 被执⾏或拒绝 如果 x 处于执⾏态,⽤相同的值执⾏ promise 如果 x 处于拒绝态,⽤相同的据因拒绝 promise
.如果 x 为 Object 或 function(不常⻅) ⾸先尝试执⾏ x.then 如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise 如果 then 是函数,将 x 作为函数的作⽤域 this 调⽤。传递两个回调函数作为参数,第⼀ 个参数叫做 resolvePromise ,第⼆个参数叫做 rejectPromise : 如果 resolvePromise 以值 y 为参数被调⽤,则运⾏ [[Resolve]](promise, y) 如果 rejectPromise 以据因 r 为参数被调⽤,则以据因 r 拒绝 promise promise.then(function(x) { console.log('会执⾏这个函数,同时传⼊ x 变量的值', x); });
.如果 resolvePromise 和 rejectPromise 均被调⽤,或者被同⼀参数调⽤了多次,则优先 采⽤⾸次调⽤并忽略其他的调⽤ 如果调⽤ then ⽅法抛出了异常 e 如果 resolvePromise 或 rejectPromise 已经被调⽤,则忽略 否则以 e 为据因拒绝 promise 如果 then 不为函数,以 x 为参数将 promise 变为已完成状态 如果 x 不为对象或者函数,以 x 为参数将 promise 变为已完成状态(重要且常⻅)
promise 解决过程
Promise 解决过程是⼀个抽象的操作,其需输⼊⼀个 promise 和⼀个值,我们表示为 [[Resolve]] (promise, x) (这句话的意思就是把 promise resolve 了,同时传⼊ x 作为值)
如果 x 有 then ⽅法且看上去像⼀个 Promise ,解决程序即尝试使 promise 接受 x 的状态;否则其 ⽤ x 的值来执⾏ promise 。
如果 promise 和 x 指向同⼀对象,以 TypeError 为据因拒绝执⾏ promise
如果 x 为 promise
如果 x 处于等待态, promise 需保持为等待态直⾄ x 被执⾏或拒绝
如果 x 处于执⾏态,⽤相同的值执⾏ promise
如果 x 处于拒绝态,⽤相同的据因拒绝 promise
容易忽略的两个点
1、promise异步执行是在 .then后.then前还是同步执行
2、如果没有return,promise会成为一个副作用,然后把undefined传递给后续的then, then并不会等待这个promise!
两个例题 例题1
scss
代码解读
复制代码
const log = console.log new Promise((res, rej) => { log(1) res() }) .then(()=>{ log(2) return new Promise((res, rej)=>{ log(3) res() }) .then(()=>{log(4)}) .then(()=>{log(5)}) }) .then(() => {log(6)})
// 1 2 3 4 5 6 例题2
scss
代码解读
复制代码
const log = console.log new Promise((res, rej) => { log(1) res() }) .then(() => { log(2) new Promise((res, rej)=>{ log(3) res() }) .then(()=>{log(4)}) .then(()=>{log(5)}) }) .then(() => { log(6) })
// 1 2 3 4 6 5 这两段代码的区别在于对Promise对象的使用方式和then方法的调用时机不同。
第一段代码使用了链式调用,即在第一个Promise的then方法中返回了一个undefined,然后继续调用后续的then方法。在第一个Promise的resolve方法被调用之后,会执行第一个then方法的回调函数,即打印2,然后创建一个新的Promise对象,并在其then方法中连续调用了两个then方法,分别打印4和5。最后,执行第一个Promise的then方法的回调函数,即打印6。
第二段代码执行顺序 123645 进入第一个promise第一个then(微任务队列1)后进入第二个promise,第二个.then进入微任务队列,第二个promise没有retrun是同步执行,第二个promise执行成功后立即执行4,子promise第二个then微任务队列(微任务队列3)挂起。至此第一个.then微任务任务执行完成,执行第二个微任务队(微任务队列2)列 log(6),微任务先进先出原则 先执行微任务队列2 再执行微任务队列3
因此,两段代码的区别在于第一个Promise对象的then方法的返回值不同(一个返回undefined,一个返回一个新的Promise对象),以及第一个Promise对象的then方法的调用时机不同(第一个代码是在第一个Promise的回调函数中调用的,第二个代码是直接在Promise对象上调用的)
promise 手搓源码
class CustomPromise {
constructor(handleFunc) {
this.status = 'pending'
this.value = undefined
this.fulfilledList = []
this.rejectedList = []
handleFunc(this.triggerResolve.bind(this), this.triggerReject.bind(this))
}
triggerResolve(val) {
// 把当前的promise状态已经变成了 resolve,要执行后续的操作
setTimeout(()=>{
if (this.status !== 'pending') return
// 传入的值是一个promise
if (val instanceof CustomPromise) {
val.then(
value => {},
err => {}
)
}else {
// resolve方法传入的是普通值
this.status = 'fulfilled'
this.value = val
// 执行已完成
this.triggerFulfilled(val)
}
},0)
}
triggerFulfilled(val) {
this.fulfilledList.forEach(item => item(val))
this.fulfilledList = []
}
triggerReject() {
}
then(onFulfilled,onRejected){
const {value,status} = this
// then ⽅法必须返回⼀个 promise 对象 promise2 = promise1.then(onFulfilled, onRejected)
const promiseInstance = new CustomPromise((onNextFulfilled, onNextRejected) => {
function onFinalFulfilled(val) {
// 如果 onFulfilled 不是函数且 promise1 状态变为已完成, promise2 必须成功执⾏并返回相同的值
if (typeof onFulfilled !== 'function') { // 如果then里面注册的不是函数把上一个promise返回结果放到下一个promise执行
onNextFulfilled(val)
}else {
/*如果 onFulfilled 是⼀个函数*/
// 判断上一步函数的执行结果的值
const res = onFulfilled(val)
// 如果 promise 和 x 指向同⼀对象,以 TypeError 为据因拒绝执⾏ promise
if (res === promiseInstance){
throw Error('两次是promises实例相等')
}
// 上一步结果是 Promise 执行 Promise.then
if (res instanceof CustomPromise) {
res.then(onNextFulfilled, onNextRejected)
// 不是Promise 直接返回上次函数返回的值
}else {
onNextFulfilled(res)
}
}
}
function onFinalRejected(error) {
if (typeof onRejected != 'function'){
onNextRejected(error)
}else {
let res = null
try {
const res = onRejected(error)
} catch (e){
onNextRejected(e)
}
if (res instanceof CustomPromise){
res.catch(onNextFulfilled, onNextRejected)
}else {
onNextRejected(res)
}
}
}
switch (status) {
case 'pending': {
this.fulfilledList.push(onFinalFulfilled)
this.rejectedList.push(onFinalRejected)
break
}
case 'fulfilled': {
onFinalFulfilled(value)
break
}
}
})
return promiseInstance
}
catch(){
}
static resolve(value) {
// 是promise直接返回promise
if (value instanceof CustomPromise) return value
// 不是promise返回对应函数或者值
return new CustomPromise(resolve => resolve(value))
}
static reject() {
}
static all(list) {
return new CustomPromise((resolve,reject) => {
// 异步执行成功数量
let count = 0
const values = []
// 循环解构循环 例 [0,promise(1000)] [1,promise(2000)]
for (const [i, promiseInstance] of list.entries()) {
// 避免参数不是promise再调用下 promise.resolve()方法
CustomPromise.resolve(promiseInstance)
.then(
res => {
values[i] = res
// 有一次resolve成功数目加1
count ++
// 总次数和all参数一致时返回总成功回调
if (count === list.length) resolve(values)
},
err => {
reject(err)
}
)
}
})
}
static race(list) {
return new CustomPromise((resolve,reject) => {
list.forEach(item => {
CustomPromise.resolve(item)
.then(
res => {
resolve(res)
},
err => {
reject(err)
}
)
})
})
}
}
const promise = function(time) {
return new CustomPromise(function(resolve, reject) {
return setTimeout(resolve, time)
})
}
const promiseInstance = promise(0)
setTimeout(function() {
promiseInstance.then(function() {console.log('hello world')})
}, 3000)
// .then(function(str) {console.log(str); return str;})
// .then(function(str2) {console.log('resolve2', str2)})
// CustomPromise.all([promise(1000), promise(3000), 'hello world'])
// .then(function() {
// console.log('all CustomPromise resolevd')
// })
promise 为什么可以链式调用因为返回的是一个promise
async awit 是promise 和Generator的语法糖