promise表示一个异步操作的最终结果.和一个promise进行交互的主要方式是通过它的then方法,该方法注册了两个回调用来接收成功后的响应和失败的原因.Promise必须提供一个then方法来访问当前或者最终的返回(可能被访问多次),同时返回一个Promise,它接受两个参数Promise.then(onFulfilled,onRejected),它们必须是函数,否则将会被忽略.onFulfilled必须在fulfilled调用(只能调用一次),onRejected必须在rejected调用(只能调用一次).
1. Promise状态
一个
Promise的当前状态只能是pending、fulfilled和rejected三种之一,当一个promise处于等待状态时,可能会变为fulfilled或者rejected状态(不可逆),但是当处于fulfilled或rejected状态时,状态不可更改.
// 定义promise的状态
const pending = 'pending'
const fulfilled = 'fulfilled'
const rejected = 'rejected'
class Promise{
constructor(executor){
// executor必须是个函数
if(typeof executor !== 'function') throw new Error('executor must be a function')
// 定义初始化的状态
this.status = pending
// 定义promise的成功值
this.value = undefined
// 定义promise失败的原因
this.reason = undefined
// 立即执行excutor函数解决new 实例出来的promise状态(可以添加逻辑判断)
try{
executor(this._resolve.bind(this),this._reject.bind(this))
}catch(e){
this._reject(e)
}
}
// 执行成功,resolve改变状态,赋值响应
_resolve(val){
if(this.status === pending){
this.status = fulfilled
this.value = val
}
}
// 执行失败,reject改变状态,赋值失败原因
_reject(val){
if(this.status === pending){
this.status = rejected
this.reason = val
}
}
}
2. Promise.then
Promise必须提供一个then方法来访问当前或最终的响应或者失败的原因.Promise.then(onFulfilled,onRejected),onFulfilled和onRejected如果不是函数将会被忽略,onFulfilled必须在Promise.resolve后才会被调用,且promise的值作为它的第一个参数;onRejected必须在Promise.reject后被调用,且promise的原因作为它的第一个参数.它们都只能被调用一次.同一个promise上then可能会被调用多次,如果resolve,那么onFulfilled会按照调用then的顺序执行,如果reject那么onReject也会按照调用then的顺序执行
class Promise{
constructor(executor){
...
// 添加成功回调函数数组,存储pending状态下then中的onFulfilled
this.fulfillQueues = []
// 添加失败回调函数数组,存储pending状态下then中的onRejected
this.rejectQueues = []
}
_resolve(val){
if(this.status === pending){
this.statsu = fulFilled
this.value = val
// resolve 按照then的调用顺序执行onFulfilled
this.fulfillQueues.forEach((fn) => fn(val))
}
}
_reject(val){
if(this.ststus === pending){
this.status = rejected
this.reason = val
// reject 按照then的调用顺序执行onRejected
this.rejectQueues.forEach((fn) => fn(val))
}
}
then(onFulfilled,onRejected){
const {value,reason,status} = this
swicth(status){
// pending状态下,将onfulfiled和onRejected存入数组等待promise状态改变
case 'pending':
this.fulfillQueues.push(onFulfilled)
this.rejectQueues.push(onRejected)
break;
// fulFilled执行
case 'fulFilled':
onFulFilled(value)
break;
// rejected执行
case 'rejected'
onRejected(reason)
break;
}
}
}
3. 链式调用
then(onFulfilled,onRejected)必须返回一个promise
promise2 = promise1.then(onFulfilled,onRejected)
如果
onFulfilled或者onRejected返回一个值x,运行promise解决程序[[resolve]](promise2,x);如果onFulfilled或者onRejected抛出一个异常e,promise2必须以e作为原因reject;如果onFulfilled不是一个函数且promise1被resolve,promise2与promise1必须以相同的值被resolve;如果onRejected不是一个函数且promise1被reject,promise2与promise1必须以相同的原因被reject
class Promise{
constructor(executor){
...
}
...
then(onFulfilled,onRejected){
const {status,value,reason} = this
const promise2 = new Promise((fulfillNext,rejectNext) => {
// 定义一个成功执行的方法
const fulFn = (value) => {
try{
// 如果onFulfilled不是函数,调用新的promise对象的resolve
if(typeof onFulfilled !== 'function'){
fulfillNext(value)
}else{
const res = onFulfilled(value)
resolvePromise(promise2,res,fulFillNext,rejectNext)
}
}catch(err){
rejectNext(err)
}
}
// 定义一个失败执行的方法
const rejFn = (err) => {
try{
// 如果onRejected不是函数,调用新的promise对象的reject
if(typeof onRejected !== 'function'){
rejectNext(err)
}else {
const res = onRejected(err)
resolvePromise(promise2,res,fulfillNext,rejectNext)
}
}catch(err){
rejectNext(err)
}
}
switch(status){
case 'pending':
this.fulfillQueues.push(fulFn)
this.rejectQueues.push(rejFn)
break
case 'fulFilled':
fulFn(value)
break;
case 'rejected':
rejFn(reason)
break;
}
})
return promise2
}
}
4. Promise解决程序
Promise解决程序是一个抽象操作,它以一个
promise和一个值传入,我们将其表示为[[resolve]](promise,x),如果x是一个具有then方法的对象或函数,就尝试采用x的status并假设x从某种程度上类似于promise,否则就是用x作为promise.resolve.这就使得Promise的实现更具有通用性:只要其暴露一个遵循Promise/A+协议的then方法即可. 如果promise和x是同一个对象,那么抛出TypeError来reject promise.否则x是一个promise:当pending时,promise保持pending直到x状态改变;当fulfilled时,promise以与x相同的值resolve;当reject时,promise以与x相同的值reject.否则x是一个对象或函数时:让then变为x.then;如果x.then抛出异常e,则将e作为原因reject promise.调用x.then(resolvePromise,rejectPromise),通过传入resolvePromise或者rejectPromise来resolve或rejectpromise,如果;两个参数同时或多次调用以第一次调用优先,then调用抛出异常时,如果rejectPromise没被调用则使用rejectPromise,否则直接rejectpromise.如果x不是对象或者函数 或者then不是函数则以xresolvepromise
class Promise{
constructor(executor){
...
}
...
resolvePromise(promise,x,resolve,reject){
if(promise === x){
throw new Error('TypeError')
}
if(x && typeof x === 'object' || typeof x === 'function'){
// 定义当前回调是否被调用
let used;
try{
const then = x.then
if(typeof then === 'function'){
x.then(y => {
if(used) return
used = true
resolvePromise(promise,y,resolve,reject)
},(e) => {
if(used) return
used = true
reject(e)
})
}else{
if(used) return
used = true
resolve(x)
}
}catch(err){
if(used) return
used = true
reject(err)
}
}else{
resolve(x)
}
}
}
因此可得出
class Promise{
constructor(executor){
...
}
...
then(onFulfilled,onRejected){
const {status,value,reason} = this
...
// 返回一个`promise`对象
return new Promise((fulfillNext,rejectNext) => {
// 定义一个成功执行的方法
const fulFn = (value) => {
try{
// 如果onFulfilled不是函数,调用新的promise对象的resolve
if(typeof onFulfilled !== 'function'){
fulfillNext(value)
}else{
判断 onFulfilled的返回是不是一个promise对象
const res = onFulfilled(value)
// 执行then方法来返回最终响应
if(res instance of Promise){
res.then(fulfillNext,rejectNext)
}else{
// 否则resolve输出
fulfillNext(res)
}
}
}catch(err){
rejectNext(err)
}
}
// 定义一个失败执行的方法
const rejFn = (err) => {
try{
// 如果onRejected不是函数,调用新的promise对象的reject
if(typeof onRejected !== 'function'){
rejectNext(err)
}else {
// 判断onRejected的返回是不是一个promise对象
const res = onRejected(err)
// 执行then方法返回响应
if(res instanceof Promise){
res.then(fulfillNext,rejectNext)
}else{
//否则reject输出
fullfillNext(res)
}
}
}catch(err){
rejectNext(err)
}
}
switch(status){
case 'pending':
this.fulfillQueues.push(fulFn)
this.rejectQueues.push(rejFn)
break
case 'fulFilled':
fulFn(value)
break;
case 'rejected':
rejFn(reason)
break;
}
})
}
}
5. resolve和reject的参数
我们还需要考虑到resolve和reject的参数,通常我们的处理只是一个变量对象,假如是一个promise对象呢
_resolve(val){
cost run = () => {
if(this.status === pending) return
this.staus = fulfilled
const fulFn = (val) => {
let cb;
while(cb = this.fulFillQueues.shift()){
cb(val)
}
}
const rejFn = (err) => {
let cb;
while(cb = this.rejectQueues.shift()){
cb(err)
}
}
if (val instanceof Promise){
val.then((value) => {
this.value = value
fulFn(value)
},err => {
this.value = err
rejFn(err)
})
}else{
this.value = value
fulFn(value)
}
}
// 支持同步Promise,多个Promise执行宏任务加入到任务队列
setTimeout(run,0)
}
6. Promise的其他方法封装
- resolve
static resolve(val){
if(val instanceof Promise) return val
return new Promise(resolve => resolve(val))
}
- reject
static reject(val){
return new Promise((resolve,reject) => reject(val))
}
- catch
static catch(onRejected){
this.then(undefined,onRejected)
}
- all
static all(list){
return new Promise((resolve,reject) => {
let reslist = []
for( let p of list){
this.resolve(p).then((res) => {
reslist.push(res)
},err => {
reject(err)
})
}
if(reslist.length === list.length){
resolve(reslist)
}
})
}
- race
static race(list){
return new Promise((resolve,reject) => {
for(let p of list){
this.resolve(p).then(res => {
resolve(res)
},err => reject(err))
}
})
}
- finally
static finally(cb){
return this.then(
value => Promise.resolve(cb()).then(() => value),
reason => Promise.resolve(cb()).then(() => throw new Error(reason))
)
}
最终产出
const pending = 'pending'
const fulfilled = 'fulfilled'
const rejected = 'rejected'
class Promise {
constructor(executor) {
if (typeof executor !== 'function') throw new Error('executor must be a function')
this.status = 'pending'
this.value = undefined
this.reason = undefined
this.fulfillQueues = []
this.rejectQueues = []
try {
executor(this._resolve.bind(this), this._reject.bind(this))
} catch (err) {
this._reject(err)
}
}
_resolve(val) {
const run = () => {
if (this.status !== pending) return
this.status = fulfilled
const fulFn = (val) => {
let cb;
while (cb = this.fulfillQueues.shift()) {
cb(val)
}
}
const rejFn = (err) => {
let cb;
while (cb = this.rejectQueues.shift()) {
cb(err)
}
}
if (val instanceof Promise) {
val.then(value => {
this.value = value
fulFn(value)
}, err => {
this.value = err
rejFn(err)
})
} else {
this.value = val
fulFn(val)
}
}
setTimeout(run, 0)
}
_reject(err) {
const run = () => {
if (this.status !== pending) return
this.status = rejected
this.value = err
let cb;
while (cb = this.rejectQueues.shift()) {
cb(err)
}
}
setTimeout(run, 0)
}
then(onFulFill, onReject) {
const { status, value, reason } = this
return new Promise((fulNext, rejNext) => {
const fulFn = (value) => {
try {
if (typeof onFulFill !== 'function') {
fulNext(value)
} else {
const res = onFulFill(value)
if (res instanceof Promise) {
res.then(fulNext, rejNext)
} else {
fulNext(value)
}
}
} catch (err) {
rejNext(err)
}
}
const rejFn = (err) => {
try {
if (typeof onReject !== 'function') {
rejNext(err)
} else {
const res = onReject(err)
if (res instanceof Promise) {
res.then(fulNext, rejNext)
} else {
fulNext(res)
}
}
} catch (err) {
rejNext(err)
}
}
switch (status) {
case 'pending':
this.fulfillQueues.push(fulFn)
this.rejectQueues.push(rejFn)
break;
case 'fulfilled':
fulFn(value)
break;
case 'rejected':
rejFn(reason)
break;
}
})
}
static resolve(val) {
if (val instanceof Promise) return val
return new Promise((resolve) => resolve(val))
}
static reject(err) {
return new Promise((resolve, reject) => reject(err))
}
static catch(cb) {
return this.then(undefined, cb)
}
static all(list) {
return new Promise((resolve, reject) => {
const reslist = []
for (let p of list) {
this.resolve(p).then(value => reslist.push(value), err => reject(err))
}
if (reslist.length === list.length) resolve(reslist)
})
}
static race(list) {
return new Promise((resolve, reject) => {
for (let p of list) {
this.resolve(p).then(value => resolve(value), err => reject(err))
}
})
}
static finally(cb) {
return this.then(
value => Promise.resolve(cb()).then(() => value),
err => Promise.resolve(cb()).then(() => { throw new Error(err) })
)
}
}