Promise Api详解和手写封装Promise对象

Promise 对象概要

  • 基础用法

  • 工作原理

  • Promise.prototype.then()

  • Promise.prototype.catch()

  • Promise.prototype.finally()

  • Promise.resolve()

  • Promise.reject()

  • Promise.all()

  • Promise.race()

  • Promise.allSettled()

  • Promise.any()

  • Promise 扩展

  • 构造函数封装 Promise 对象

  • class 类封装 Promise 对象

一、Promise 对象介绍

Promise 是一个异步解决方案,其本质是一个构造函数,调用时需要使用 new 命令符。该构造函数接收一个函数作为参数,返回一个 Promise 实例对象。该函数参数有两个参数,且这两个参数都是函数,第一个函数参数(resolve)在异步成功时调用,一旦调用过后,Promise 的状态就会变成已完成(成功)。第二个函数参数(reject)在异步失败时调用,调用过后,Promise 的状态就会变成已失败,而且 Promise 的状态只会改变一次,一旦状态改变后,就不会再次发生变化,且任何时候调用 Promise 都是能得到这个结果。

Promise 对象有三个状态,分别是初始化时的未完成 pending,已成功 resolvedfulfilled,,已失败 rejected

Promise 对象状态的改变有两种情况,一种是由未完成变成已完成,即从 pendingresolvedfulfilled,另一种情况是由未完成到已失败,即从 pendingrejected

1、Promise 的基本用法。

const p = new Promise((resolve, reject) => { // 返回一个 promise 实例对象
    if(true) {
        resolve();
    } else {
        reject();
    }
})

console.log(p);

2、Promise 的工作流程。Promise 的参数函数,称之为 执行器 函数,当对 Promise 使用 new 命令符时,执行器函数会立即执行,且执行器函数内部的代码为同步代码。如果 Promise 存在异步操作,当操作成功时,调用执行器函数的第一个参数函数 resolve(),使得 Promise 的状态会变为已完成;当操作结果失败时,则调用 Promise 的第二个参数函数 reject(),使得 Promise 状态变为已失败。

const p = new Promise((resolve, reject) => {
    console.log('hello');
    if(true) {
        resolve();
    } else {
        reject();
    }
})

console.log('world');
// 输出结果,先输出 'hello',在输出 'world'

上面代码的输出结果是,先输出 'hello', 再输出 'world',证明执行器函数内部的代码是同步代码。

Promise执行器函数内部执行 resolve()reject()回调的时候传递的参数,就是返回的promise实例对象的结果值。

const p = new Promise((resolve, reject) => {
    if(true) {
        resolve('成功');
    } else {
        reject('失败');
    }
})
// new Promise中执行了resove('成功')回调
// 因此返回的实例对象p的状态属于成功,resolve('成功')传递的值就是p的值
// 在控制台可以看到 p的属性[[promiseResult]]: '成功'
console.log(p) 

3、Promise.prototype.then() 方法,Promise 执行的返回结果是一个 Promise 实例对象,该实例对象有个 then() 方法,接收两个参数函数。当 Promise 的状态会变为已完成(成功)时,调用 then() 方法的第一个回调函数。当 Promise 的状态变为失败或抛出错误时,则调用 then() 方法的第二个参数函数。then()方法返回一个新的promise实例对象,它的状态由then()方法的执行的回调返回值决定:

(1)当then方法的回调的返回值是一个非promise对象时,then()方法返回的是一个成功的promise实例对象。

(2)当then方法的回调的返回值是一个promise对象时,该对象的状态决定了最终then()方法返回的promise对象的状态,而且该对象的值就是then()方法返回的promise对象的值。

const p = new Promise((resolve, reject) => {
    resolve('成功');
})

//(1)
const res = p.then(value => {
    return 123
}, reason => {
    console.log(reason);
})
res.then(value => console.log(value)) // 输出123

// p是一个成功的promise对象,因此执行then()方法的第一个回调
// 该回调返回数字123(非promise对象)
// 因此最终的返回的promise对象res是一个成功的promise对象,值为123

//(2)then回调是个成功的promise
const res = p.then(value => {
    return new Promise((resolve, reject) => {
        resolve('success');
    })
}, reason => {
    console.log(reason);
})
res.then(value => console.log(value)) // 输出success
// p是一个成功的promise对象,因此执行then()方法的第一个回调
// 该回调返回一个新的成功的promise对象,值为success
// 因此最终的返回的promise对象res是一个成功的promise对象,值为success

//(2)then回调是个失败的promise
const res = p.then(value => {
    return new Promise((resolve, reject) => {
        reject('fail');
    })
}, reason => {
    console.log(reason);
})
res.then(() => (), reason => console.log(reason)) // 输出fail
// p是一个成功的promise对象,因此执行then()方法的第一个回调
// 该回调返回一个新的失败的promise对象,值为fail
// 因此最终的返回的promise对象res是一个失败的promise对象,值为fail

then()方法返回的结果依旧是一个promise实例对象,因此,可以链式调用then()方法。

const p = new Promise((resolve, reject) => {
    if(true) {
        resolve('成功');
    } else {
        reject('失败');
    }
})

p.then(value => {
    console.log(value);
}, reason => {
    console.log(reason);
}).then()

Promise的执行器函数抛出错误时,then()方法会执行第二个回调。

const p = new Promise((resolve, reject) => {
    throw '失败了'
})

p.then(value => alert(value), reason => console.log(reason))
// 执行then()方法的第二个回调,输出 ‘失败了’

4、Promise.prototype.catch() 方法,专门用来指定 Promise 实例对象发生错误时的回调,因此,then() 方法里面可以不写失败回调,而是把失败回调最后放到 catch() 方法里面。catch() 方法是 then(null, rejection)then(undefined, rejection) 的别名, 本质依旧是一个 then() 方法。

const p = new Promise((resolve, reject) => {
    if(true) {
        resolve();
    } else {
        reject();
    }
})

p.then(vlaues => {
    console.log('成功');
}).catch(reason => {
    console.log('失败');
})

5、Promise.prototype.finally() 方法,用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。

const p = new Promise((resolve, reject) => {
    if(true) {
        resolve();
    } else {
        reject();
    }
})

p.then(vlaues => {
    console.log('成功');
}).catch(reason => {
    console.log('失败');
}).finally(() => {
    console.log('这是最后执行的回调');
})

6、Promise.resolve() 方法,接收一个值作为参数,用于将参数值快速转化成一个 Promise 对象实例。该方法返回的 Promise 对象的结果由参数决定。

如果参数是一个非 Promise 对象,无论是 nullundefined、还是其他类型数据,返回的都是一个状态为成功的 Promise 实例对象。

/ p 是一个状态成功的 Promise 实例对象
const p = Promise.resolve(9527)

p.then(value => console.log(value))
// 输出结果 9527

如果参数是一个 Promise 对象,则返回的 Promise 实例对象的状态由该参数的状态决定。

 const p = Promise.resolve(new Promise((resolve, reject) => {
    if(true) {
        resolve();
    } else {
        reject();
    }
}))

// 实例对象 p 的状态参数 new Promise(...) 的状态决定
// 当参数对象的状态为成功,p 的状态就成功,而且参数对象返回的成功的值就是 p 的值
// 当参数对象的状态为失败,p 的状态就失败,而且参数对象返回的失败的值就是 p 的值

7、Promise.reject() 方法,快速返回一个 Promise 对象实例,该实例的状态为 rejected

const p = Promise.reject('出错了')
p.catch(reason => console.log(reason))

8、Promise.all() 方法,用于将多个 Promise 实例对象,包装成一个新的 Promise 实例,该方法接收一个 Promise 对象组成的数组作为参数。当所有数组成员的 Promise 状态都为成功时,Promise.all() 返回的实例的状态就为成功。当数组成员中有一个 Promise 对象的状态为失败,则整个 Promise.all() 返回的实例的状态就为失败。且 Promise.all() 方法的返回结果就是各个 Promise 对象的成功返回值组成的一个数组。

const p1 = new Promise((resolve, reject) => {
    resolve('成功')
})
const p2 = Promise.resolve('success')

const pro = Promise.all([p1, p2])
pro.then(values => console.log(values))
// pro 的状态为成功,输出结果为 ['成功', 'success']

9、Promise.race() 方法,用于将多个 Promise 实例对象,包装成一个新的 Promise 实例,该方法接收一个 Promise 对象组成的数组作为参数。返回的实例对象的状态由数组成员中最先改变状态的 Promise 对象决定。该最先改变状态的 Promise 的状态为成功时,Promise.race() 返回的实例的状态就为成功。该最先改变状态的 Promise 的状态为失败,则整个 Promise.race() 返回的实例的状态就为失败。且 Promise.race() 方法结果就是最先改变状态的 Promise 对象的返回结果。

const p1 = new Promise((resolve, reject) => {
    resolve('成功')
})
const p2 = Promise.resolve('success')
const pro = Promise.race([p1, p2])

pro.then(values => console.log(values))
// pro 的状态为成功,输出结果为 ['成功']

10、Promise.allSettled() 方法,用于确保一组异步操作都完成后(不论成功或失败,全都返回结果),在执行下一步操作。该方法接收一个 Promise 对象组成的数组作为参数。返回的新的 Promise 实例,一旦发生状态变更,状态总是 fulfilled ,不会变成 rejected

const p1 = new Promise((resolve, reject) => {
    setTimeout(()=>{
    resolve('成功');
    console.log(8888);
}, 1000)
})
const p2 = Promise.resolve('success')
await Promise.allSettled([p1, p2])

console.log(9999);
// 结果,等待1秒后,先输出 8888,再输出 9999

11、Promise.any() 方法,用于将多个 Promise 实例对象,包装成一个新的 Promise 实例,该方法接收一个 Promise 对象组成的数组作为参数。数组成员的 Promise 只要有一个状态变为成功时,Promise.any() 返回的实例的状态就为成功,Promise.any() 方法的值就是第一个成功的 Promise 对象返回的值。当数组成员中所有的 Promise 对象的状态都为失败时,则整个 Promise.any() 返回的实例的状态就为失败。

const p1 = new Promise((resolve, reject) => {
    reject('失败')
})
const p2 = Promise.resolve('success')
const pro = Promise.any([p1, p2])

pro.then(values => console.log(values)).catch(err => console.log(err))
// 输出结果,'success'

二、Promise 扩展

1、Promise 对象有三种状态,初始化时的未完成状态 pending,成功时的状态 resolved (fulfilled) 及失败时的状态 rejectedPromise 对象状态的变化只要两种情况,pending => fulfilledpending => rejected。而改变 Promise 对象状态的方式共有三种。

(1)、调用 resolve(),一旦在 Promise 对象内部调用了该方法,其状态就会变成已完成(成功)。

(2)、调用 reject(),该方法调用后,Promise 对象的状态就会变成已失败。

(3)、直接抛出错误 throw new Error('失败')

const p = new Promise((resolve, reject) => {
    throw new Error('失败了')
})
p.catch(err => console.log(err))

2、为 Promise 对象指定都多个回调,在 Promise 状态发生改变时,所有指定的回调都会执行。

 const p = Promise.resolve('成功')
p.then(value => console.log('111'))
p.then(value => console.log('222'))
// 输出结果,先输出 111,再输出 222,两个 then() 方法的回调都执行

三、Promise 封装

1、使用构造函数封装。

export default function Promise(excutor) {
    this.promiseState = 'pending';
    this.promiseResult = null;
    this.callbacks = [];

    // 执行器函数成功回调
    const resolve = (data) => {
        // 调用过后,改变 promise 状态为成功
        if(this.promiseState !== 'pending') return;
        this.promiseState = 'fulfilled';
        this.promiseResult = data;

        // 执行异步任务的回调
        this.callbacks.length && setTimeout(() => {
            this.callbacks.forEach(item => {
                item.onResolved(data);
            });
        });
    };

    // 执行器函数失败回调
    const reject = (data) => {
        // 调用过后,改变 promise 状态为失败
        if(this.promiseState !== 'pending') return;
        this.promiseState = 'rejected';
        this.promiseResult = data;

        // 执行异步任务的回调
        this.callbacks.length && setTimeout(() => {
            this.callbacks.forEach(item => {
                item.onRejected(data);
            });
        });
    };
    
    try {
        excutor(resolve, reject);
    } catch(e) {
        reject(e);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
    (typeof onResolved !== 'function') && (onResolved = values => values);
    (typeof onRejected !== 'function') && (onRejected = reason => {
        throw reason;
    });
    return new Promise((resolve, reject) => {
        const callback = onCallbackType => {
            try {
                // 获取promise成功时then方法的第一个回调的结果值
                const result = onCallbackType(this.promiseResult);
                if(result instanceof Promise) {
                    // 结果是一个promise对象
                    result.then(v => {
                        resolve(v);
                    }, r => {
                        reject(r);
                    });
                } else {
                    // 结果是一个非promise对象
                    resolve(result);
                }
            } catch(e) {
                reject(e);
            }
        }

        // Promise 状态变为成功时,执行 then 方法的第一个回调
        if(this.promiseState === 'fulfilled') {
            setTimeout(() => {
                callback(onResolved);
            });
        }
    
        // Promise 状态变为失败时,执行 then 方法的第二个回调
        if(this.promiseState === 'rejected') {
            setTimeout(() => {
                callback(onRejected);
            });
        }
        
        // 当promise存在异步任务,把then回调储存起来
        if(this.promiseState === 'pending') {
            this.callbacks.push({
                onResolved: () => {
                    callback(onResolved);
                },
                onRejected: () => {
                    callback(onRejected);
                }
            });
        }
    });
}

// 添加catch方法
Promise.prototype.catch = function(onRejected) {
    return this.then(undefined, onRejected);
}

// 添加finally方法
Promise.prototype.finally = function(callback) {
    return this.then(v => {
        callback();
        return Promise.resolve(v);
    }, r => {
        callback();
        throw r;
    })
}

// 添加resolve方法
Promise.resolve = function(value) {
    return new Promise((resolve, reject) => {
        if(value instanceof Promise) {
            value.then(v => {
                resolve(v);
            }, r => {
                reject(r);
            });
        } else {
            resolve(value);
        }
    });
}

// 添加reject方法
Promise.reject = function(reason) {
    return new Promise((resolve, reject) => {
        reject(reason);
    });
}

// 添加all方法
Promise.all = function(promiseArr) {
    let count = 0;
    let arr = [];
    return new Promise((resolve, reject) => {
        promiseArr.forEach((item, index) => {
            item.then(v => {
                count++;
                arr[index] = v;
                (count === promiseArr.length) && resolve(arr);
            }, r => {
                reject(r);
            });
        });
    });
}

// 添加race方法
Promise.race = function(promiseArr) {
    return new Promise((resolve, reject) => {
        promiseArr.forEach(item => {
            item.then(v => {
                resolve(v);
            }, r => {
                reject(r);
            });
        });
    });
}

// 添加any方法
Promise.any = function(promiseArr) {
    let count = 0;
    return new Promise((resolve, reject) => {
        promiseArr.forEach(item => {
            item.then(v => {
                resolve(v);
            }, r => {
                count++;
                (count === promiseArr.length) && reject('All promises were rejected');
            });
        });
    });
}

// 添加allSettled方法
Promise.allSettled = function(promiseArr) {
    let count = 0;
    let arr = [];
    return new Promise((resolve, reject) => {
        promiseArr.forEach((item, index) => {
            item.then(v => {
                arr[index] = {
                    status: 'fulfilled',
                    value: v
                };
                count++;
                (count === promiseArr.length) && resolve(arr);
            }, r => {
                arr[index] = {
                    status: 'rejected',
                    reason: r
                };
                count++;
                (count === promiseArr.length) && resolve(arr);
            });
        });
    });
}

  1. 使用 class 类封装。

 export default class Promise {
    constructor(excutor) {
        this.promiseState = 'pending';
        this.promiseResult = null;
        this.callbacks = [];

        // 执行器函数成功回调
        const resolve = (data) => {
            // 调用过后,改变 promise 状态为成功
            if(this.promiseState !== 'pending') return;
            this.promiseState = 'fulfilled';
            this.promiseResult = data;

            // 执行异步任务的回调
            this.callbacks.length && setTimeout(() => {
                this.callbacks.forEach(item => {
                    item.onResolved(data);
                });
            });
        };

        // 执行器函数失败回调
        const reject = (data) => {
            // 调用过后,改变 promise 状态为失败
            if(this.promiseState !== 'pending') return;
            this.promiseState = 'rejected';
            this.promiseResult = data;

            // 执行异步任务的回调
            this.callbacks.length && setTimeout(() => {
                this.callbacks.forEach(item => {
                    item.onRejected(data);
                });
            });
        };
        
        try {
            excutor(resolve, reject);
        } catch(e) {
            reject(e);
        }
    }

    // 添加then方法
    then(onResolved, onRejected) {
        (typeof onResolved !== 'function') && (onResolved = values => values);
        (typeof onRejected !== 'function') && (onRejected = reason => {
            throw reason;
        });
        return new Promise((resolve, reject) => {
            const callback = onCallbackType => {
                try {
                    // 获取promise成功时then方法的第一个回调的结果值
                    const result = onCallbackType(this.promiseResult);
                    if(result instanceof Promise) {
                        // 结果是一个promise对象
                        result.then(v => {
                            resolve(v);
                        }, r => {
                            reject(r);
                        });
                    } else {
                        // 结果是一个非promise对象
                        resolve(result);
                    }
                } catch(e) {
                    reject(e);
                }
            }

            // Promise 状态变为成功时,执行 then 方法的第一个回调
            if(this.promiseState === 'fulfilled') {
                setTimeout(() => {
                    callback(onResolved);
                });
            }
        
            // Promise 状态变为失败时,执行 then 方法的第二个回调
            if(this.promiseState === 'rejected') {
                setTimeout(() => {
                    callback(onRejected);
                });
            }
            
            // 当promise存在异步任务,把then回调储存起来
            if(this.promiseState === 'pending') {
                this.callbacks.push({
                    onResolved: () => {
                        callback(onResolved);
                    },
                    onRejected: () => {
                        callback(onRejected);
                    }
                });
            }
        });
    }

    // 添加catch方法
    catch(onRejected) {
        return this.then(undefined, onRejected);
    }

    // 添加finally方法
    finally(callback) {
        return this.then(v => {
            callback();
            return Promise.resolve(v);
        }, r => {
            callback();
            throw r;
        })
    }

    // 添加resolve方法
    static resolve(value) {
        return new Promise((resolve, reject) => {
            if(value instanceof Promise) {
                value.then(v => {
                    resolve(v);
                }, r => {
                    reject(r);
                });
            } else {
                resolve(value);
            }
        });
    }

    // 添加reject方法
    static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason);
        });
    }

    // 添加all方法
    static all(promiseArr) {
        let count = 0;
        let arr = [];
        return new Promise((resolve, reject) => {
            promiseArr.forEach((item, index) => {
                item.then(v => {
                    count++;
                    arr[index] = v;
                    (count === promiseArr.length) && resolve(arr);
                }, r => {
                    reject(r);
                });
            });
        });
    }

    // 添加race方法
    static race(promiseArr) {
        return new Promise((resolve, reject) => {
            promiseArr.forEach(item => {
                item.then(v => {
                    resolve(v);
                }, r => {
                    reject(r);
                });
            });
        });
    }

    // 添加any方法
    static any(promiseArr) {
        let count = 0;
        return new Promise((resolve, reject) => {
            promiseArr.forEach(item => {
                item.then(v => {
                    resolve(v);
                }, r => {
                    count++;
                    (count === promiseArr.length) && reject('All promises were rejected');
                });
            });
        });
    }

    // 添加allSettled方法
    static allSettled(promiseArr) {
        let count = 0;
        let arr = [];
        return new Promise((resolve, reject) => {
            promiseArr.forEach((item, index) => {
                item.then(v => {
                    arr[index] = {
                        status: 'fulfilled',
                        value: v
                    };
                    count++;
                    (count === promiseArr.length) && resolve(arr);
                }, r => {
                    arr[index] = {
                        status: 'rejected',
                        reason: r
                    };
                    count++;
                    (count === promiseArr.length) && resolve(arr);
                });
            });
        });
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值