Promise特性和实现

109 阅读3分钟

一、Promise基本特性

  1. Promise三种状态:pending(进行中)、fulfilled(已完成)、rejected(已失败)
  2. Promise对象接受一个回调函数作为参数, 该回调函数接受两个参数,分别是成功时的回调resolve和失败时的回调reject;另外resolve的参数除了正常值以外, 还可能是一个Promise对象的实例;reject的参数通常是一个Error对象的实例。
  3. then方法返回一个新的Promise实例,并接收两个参数onResolved(fulfilled状态的回调);onRejected(rejected状态的回调,该参数可选)
  4. Promise.all()方法将多个多个Promise实例,包装成一个新的Promise实例,该方法接受一个由Promise对象组成的数组作为参数(Promise.all()方法的参数可以不是数组,但必须具有Iterator接口,且返回的每个成员都是Promise实例),注意参数中只要有一个实例触发catch方法,都会触发Promise.all()方法返回的新的实例的catch方法,如果参数中的某个实例本身调用了catch方法,将不会触发Promise.all()方法返回的新实例的catch方法

二、Promise优点

1. 统一异步的API

promise逐渐被用作浏览器的异步API,统一现在各种各样的API,以及不兼容的模式和手法。

2. Promise比事件更适合处理一次性结果

promise的链式处理,在结果计算出来之前或之后注册回调函数都是可以的,都可以拿到正确的值。更适合处理一次性的结果,但不能使用 Promise 处理多次触发的事件。

3. 解决了回调地狱

采用链式写法,解决了回调地狱的问题,将异步操作以同步操作的流程表达出来。

4. 更丰富的错误处理方式

promise有更好的错误处理方式,包含了异常处理。

5. 分离了异步数据获取和业务逻辑,利于代码的复用

三、Promise缺点

  1. 无法取消Promise,一旦新建它就会立即执行,无法中途取消。
  2. 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
  3. 当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
  4. Promise 真正执行回调的时候,定义 Promise 那部分实际上已经走完了,所以 Promise 的报错堆栈上下文不太友好。

四、Promise状态转换

1.初始化,状态:pending

2.当调用resolve(成功),状态:pending=>fulfilled

3.当调用reject(失败),状态:pending=>rejected

pending、fulfilled、rejected(未决定,履行,拒绝),

同一时间只能存在一种状态,且状态一旦改变就不能再变

promise是一个构造函数,promise对象代表一项有两种可能结果(成功或失败)的任务,它还持有多个回调,出现不同结果时分别发出相应回调。

五、代码实现

(1)简单代码实现

class Promise {
    constructor(executor) {
        this.state = 'pending';
        this.value = undefined;
        this.reason = undefined;
        let resolve = value => {
            if (this.state === 'pending') {
                this.state = 'fulfilled';
                this.value = value;
            }
        };
        let reject = reason => {
            if (this.state === 'pending') {
                this.state = 'rejected';
                this.reason = reason;
            }
        };
        try {
            //立即执行函数
            executor(resolve, reject);
        } catch (err) {
            reject(err);
        }
    }
    then(onFulfilled, onRejected) {
        if (this.state === 'fulfilled') {
            let x = onFulfilled(this.value);
        };
        if (this.state === 'rejected') {
            let x = onRejected(this.reason);
        };
    }
}

(2)面试版

function myPromise(constructor) {
    let self = this;
    self.status = "pending"
    self.value = undefined
    self.reason = undefined
    function resolve(value) {
        //两个 === "pending"保证状态是不可逆的
        if (self.status === "pending") {
            self.value = value;
            self.status = "resolved";
        }
    }
    function reject(reason) {
        //两个 === "pending"保证状态是不可逆的
        if (self.status === "pending") {
            self.reason = reason;
            self.status = "rejected";
        }
    }
    //捕获构造异常
    try {
        constructor(resolve, reject);
    } catch (e) {
        reject(e)
    }
}

myPromise.prototype.then = function (onFulfilled, onRejected) {
    let self = this;
    switch (self.status) {
        case "resolve": onFulfilled(self.value); break;
        case "reject": onRejected(self.reason);break;
        default;
    }
}

//测试
var p = new myPromise(function (resolve, reject) {
    resolve(1)
})
p.then(function(x) {
    console.log(x)//1
})