开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
Promise
Promise的对象是一个代理对象,被代理的值在对象创建时可能是未知的,另外它允许你为异步操作的成功和失败分别绑定相应的处理方法。 常用于控制异步操作的执行顺序,而且可以让异步方法像同步方法那样返回值。它不能立即取得异步方法的返回值,但是它可以代理这个值,一旦异步操作完成,就会以及将值传递给相应的处理方法。 一个对象有以下几种状态:
pending
: 初始状态,既不是成功,也不是失败状态。fulfilled
: 意味着操作成功完成。rejected
: 意味着操作失败。
一个对象的状态可以从pending
变成fulfilled
或rejected
,pending
状态一经改变意味着此Promise对象的执行器函数已执行完毕且状态无法再次变更。当状态变更为fulfilled
时传递一个成功值给Promise.then()
的第一个回调函数;当已状态变更为rejected
时传递一个失败信息给给Promise.then()
的第二个回调函数以及Promise.catch()
的第一个回调函数。因为Promise.then()
和Promise.catch()
方法都会返回一个新的对象, 所以它们可以被链式调用。
Promise.resolve()
Promise
并非一开始就处于待定状态,然后通过执行器函数才能转换为落定状态。通过调用Promise.resolve()
静态方法,可以直接实例化一个已经为完成状态的Promise
对象。
以下的两个Promise对象是一样的:
let p1 = new Promise((resolve,reject)=>resolve())
let p2 = Promise.resolve()
当Promise.resolve()
传入的参数可以是任何东西,包括一个错误对象 new Error()
。如果传入的是一个Promise
对象的话,就相当于给了一个空包装。因此Promise.resolve()
可以说是一个幂等方法。
比如:
let p1 = Promise.resolve(123)
console.log(p1===Promise.resolve(Promise.resolve(p1)))//true
Promise.reject()
与Promise.resolve()
类似,首先会实例化一个处理失败的Promise
对象,并抛出一个异步错误。
但是并没有照搬resolve
的幂等逻辑,进行嵌套reject
包装时,会抛出错误理由。
Promise的实例的静态方法
Promise 实例的方法是连接外部同步代码与内部异步代码的桥梁。这些方法可以访问异步操作所返回的数据,对异步成功或异步失败的数据进行操作,或者添加只有达到某种状态后才会执行的代码。
-
Promise.then()
是为Promise
实例添加结果处理程序的主要方法。这个then
最多接收两个参数。onResolve
和onRejected
处理程序。这两个参数都是可选的,如果提供的话,则会在Promise
分别进入fulfilled
和rejected
状态时执行。 -
Promise.catch()
方法用于给Promise
添加拒绝处理方法。这个方法只接收一个参数onRejected
处理程序,相当调用Promise.then(null,onRejected)
方法。
以下内容难度飙升↑
promise.all()
使用该方法创建的Promise
对象会在一组Promise
对象解决之后再解决。 如果接收的数组中存在非Promise
对象的话,会直接当做Promise.resolve()
抛出。。这个方法接收一个可迭代的对象,返回一个新Promise
:
let p1 = Promise.all([Promise.resolve(1),Promise.resolve(2),3,'4',true])
p1.then(res=>{
console.log(res);//[1,2,3,'4',true]所有Promise执行成功,返回该数组执行的结果
})
let p2 = Promise.all([Promise.reject(1),Promise.resolve(2),3,'4',true])
p2.then(res=>{
console.log('处理成功')//数组中有一个Promise执行失败都不会执行onResoled程序
},err=>{
console.log('处理失败');//onRejected程序执行。
})
- Promise.rece()和all类似,接收的参数为一个可迭代的对象。但是只返回第一个执行结束的Promise对象。如果第一个执行结束的状态为
fulfilled
则把返回值传递给onResolved
程序,如果为rejected
状态,则传递给onRejected
程序。
简单还原一个Promise
class myPromise {
constructor(executor) {//传入一个执行器函数executor
this.status = 'pending'//设置初始状态为pending
this.value = null//保存需要抛出的值
this.onFulfilledCallbacks = []//保存成功的回调
this.onRejectedCallbacks = []//保存失败的回调
try {
executor(this.resolve.bind(this), this.reject.bind(this))
} catch (err) {//使用try catch捕获代码逻辑错误,存在则抛出
this.reject(err)
}
}
resolve(value) {
if (this.status != 'pending') return
this.status = 'fullfilled'
this.value = value
//调用then里面的回调
while (this.onFulfilledCallbacks.length) {
this.onFulfilledCallbacks.shift()(this.value)
}
}
reject(val) {
if (this.status != 'pending') return
this.value = val
this.status = 'rejected'
while (this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(this.value)
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
onRejected = typeof onRejected === 'function' ? onRejected : val => { throw val }
var thenpromise = new myPromise((resolve, reject) => {
const resolvePromose = cb => {
setTimeout(() => {
try {
const x = cb(this.value)
if (x === thenpromise) {
throw new Error('不能返回自身。。。')
}
if (x instanceof myPromise) {
x.then(resolve, reject)
} else {
resolve(x)
}
} catch (err) {
reject(err)
throw new Error(err)
}
})
}
if (this.status === 'fullfilled') {
resolvePromose(onFulfilled) //判断onFulfilled返回值内容
} else if (this.status === 'rejected') {
resolvePromose(onRejected)
} else if (this.status === 'pending') {//如果状态没改变则保存起来,在resolve中执行点then的回调
this.onFulfilledCallbacks.push(resolvePromose.bind(this, onFulfilled))
this.onRejectedCallbacks.push(resolvePromose.bind(this, onRejected))
}
})
return thenpromise
}
static all(promise){//传入一个可迭代的对象promise
let result = []
let count = 0
return new myPromise((resolve,reject)=>{//便于链式调用返回一个新的promise对象
const addResolve = (val,index)=>{//验证数组中的执行结果是否全部执行完毕
// result.push(val)
result[index] = val
count++
if(count === promise.length){//如果长度相等则直接抛出
return resolve(result)
}
}
promise.forEach((promise,index) => {//循环这个数组
if(promise instanceof myPromise){//如果传入的参数是一个promise对象
promise.then(res=>{//则在该promise的.then方法中将结果和下标保存
addResolve(res,index)
},err=>{
return reject(err)//如果执行出错则直接返回
})
}else{
addResolve(promise,index)
}
});
})
}
static race(promise){
return new myPromise((resolve,reject)=>{
promise.forEach((item,index,arr)=>{
if(item instanceof myPromise){
item.then(res=>{//在每个promise的.then中放入onResolved程序如果成功则直接返回
resolve(res)
},err=>{
reject(err)//在每个promise的.then中放入onRejected程序如果失败则直接返回
})
}else{
resolve(item)
}
})
})
}
}
写了这么多可以调试一下啦~~~嘿嘿
const p2 = new myPromise((resolve,reject)=>{
setTimeout(()=>{
resolve('ok1')
},100)
})
const p3 = new myPromise((resolve,reject)=>{
setTimeout(()=>{
resolve('ok2')
},200)
})
const p4 = new myPromise((resolve,reject)=>{
setTimeout(()=>{
resolve('ok3')
},300)
})
const pp = function(){
console.log('pp');
}
myPromise.all([p2,p3,p4,pp]).then(res=>{
console.log(res);
})
myPromise.race([p2,p3,p4]).then(res=>{
console.log(res);
})
-
Promise.all()
成功打印 -
Promise.rece()
成功打印
----到这里就结束啦,这就是我的Promise从理解到手写的进阶之路