Promise的定义&&使用&&原理

170 阅读1分钟

Promise是什么?

Promise是一种异步方法,可以让代码变得简洁,提高代码的阅读性,从而有效的解决回调地狱的问题~

Promise的使用

首先我们要知道,Promise有三种状态,分别是pedding、rejected和resolved,一旦状态发生改变,就不会再变了。

当我们使用Promise时,通过Promise的构造函数new一个实例,它接收一个函数作为参数,这个函数里面有两个参数,分别是resolve和reject,resolve将promise的状态变为成功(resolved),reject将promise的状态变为失败(rejected)

let p = new Promise(function(resolve, reject){
    setTimeout(function(){
        var num = Math.ceil(Math.random()*20); //生成1-10的随机数
        console.log('随机数生成的值:',num)
        if(num<=10){
            resolve(num); //利用resolve传值
        }
        else{
            reject('数字太于10了即将执行失败回调'); //利用reject传值
        }
    }, 2000);
})
p.then(function(data){
    console.log('resolved成功回调');
    console.log('成功回调接受的值:',data);
}, 
function(reason){
    console.log('rejected失败回调');
    console.log('失败执行回调抛出失败原因:',reason);
})

实例创建完成后,可以使用then方法分别指定成功或失败的回调函数,也可以使用catch捕获失败,then和catch最终返回的也是一个Promise,所以可以链式调用。

Promise的其他方法

  • Promise.reject()创建一个状态为失败的promise对象
  • Promise.resolve()创建一个状态为成功的promise对象
  • Promise.all([数组])传入的参数是一个数组,数组中有多个promise,只有当所有的promise的状态都有成功时,才返回一个成功的promise对象。当需要执行多个异步任务,而各异步任务之间又没有依赖性时,可以用Promise.all方法,这样可以提高请求的效率,因为各个promise是并发执行的。
  • Promise.any([数组])传入的参数是一个数组,数组中有多个promise,只要有一个promise的状态为成功时,就会返回一个成功的promise对象。
  • Promise.race([数组])传入的参数是一个数组,数组中有多个promise,将最先改变状态的promise的状态作为该promise的状态

Promise的原理

手写一个简单的Promise 我们知道Promise里面有三种状态,分别是PENDING、FULFILLED、REJECTED,先在类中定义三个常量

    static PENDING = '待定';
    static FULFILLED = '成功';
    static REJECTED = '拒绝';

当我们new一个Promise时,还要用constructor来初始化一些东西。

constructor(func) {
        //初始化状态是待定的
        this.status = '待定';
        //promise当前所拿到的数据的值
        this.result = null;
        //resolve的回调队列
        this.resolveCallbacks = [];
        //reject的回调队列
        this.rejectCallbacks = [];
        try {
            //改变this的指向,使resolve里面的this一直指向pormise对象
            func(this.resolve.bind(this), this.reject.bind(this));
        } catch (error) {
            this.reject(error);
        }
    }

我们知道new Promise的时候,是需要传入一个函数的,这个函数又有两个参数,这两个参数都是函数,分别是resolve和reject,那么我们就来写一写resolve和reject方法吧

我们知道,resolve方法和reject方法都不是同步执行的,所以这里用了setTimeout()来将resolve和reject的内部执行模拟为异步。

resolve(result) {
        setTimeout(() => {
            if (this.status === Commitment.PENDING) {
                this.status = Commitment.FULFILLED;
                this.result = result;
                this.resolveCallbacks.forEach(callback => {
                    callback(result);
                })
            }
        })
    }

reject(result) {
        setTimeout(() => {
            if (this.status === Commitment.PENDING) {
                this.status = Commitment.REJECTED;
                this.result = result;
                this.rejectCallbacks.forEach(callback => {
                    callback(result);
                })
            }
        })
    }

最后再写then方法

 then(onFULFILLED, onREJECTED) {
        return new Commitment((resolve, reject) => {
            onFULFILLED = typeof onFULFILLED === 'function' ? onFULFILLED : () => { };
            onREJECTED = typeof onREJECTED === 'function' ? onFULFILLED : () => { };
            if (this.status === Commitment.PENDING) {
                this.resolveCallbacks.push(onFULFILLED);
                this.rejectCallbacks.push(onREJECTED);
            }
            if (this.status === Commitment.FULFILLED) {
                setTimeout(() => {
                    onFULFILLED(this.result);
                })
            }
            if (this.status === Commitment.REJECTED) {
                setTimeout(() => {
                    onREJECTED(this.result);
                })
            }
        })
    }

总的代码

class Commitment {
    //常量全用大写字母来写
    static PENDING = '待定';
    static FULFILLED = '成功';
    static REJECTED = '拒绝';
    constructor(func) {
        this.status = '待定';
        this.result = null;
        this.resolveCallbacks = [];
        this.rejectCallbacks = [];
        // try {
        //     func(this.resolve.bind(this), this.reject.bind(this));
        // } catch (error) {
        //     this.reject(error);
        // }
        console.log(this)
        func(this.resolve, this.reject);
    }

    resolve(result) {
        console.log(this)
        setTimeout(() => {
            console.log(this)
            if (this.status === Commitment.PENDING) {
                this.status = Commitment.FULFILLED;
                this.result = result;
                this.resolveCallbacks.forEach(callback => {
                    callback(result);
                })
            }
        })
    }

    reject(result) {
        setTimeout(() => {
            if (this.status === Commitment.PENDING) {
                this.status = Commitment.REJECTED;
                this.result = result;
                this.rejectCallbacks.forEach(callback => {
                    callback(result);
                })
            }
        })
    }

    then(onFULFILLED, onREJECTED) {
        return new Commitment((resolve, reject) => {
            onFULFILLED = typeof onFULFILLED === 'function' ? onFULFILLED : () => { };
            onREJECTED = typeof onREJECTED === 'function' ? onFULFILLED : () => { };
            if (this.status === Commitment.PENDING) {
                this.resolveCallbacks.push(onFULFILLED);
                this.rejectCallbacks.push(onREJECTED);
            }
            if (this.status === Commitment.FULFILLED) {
                setTimeout(() => {
                    onFULFILLED(this.result);
                })
            }
            if (this.status === Commitment.REJECTED) {
                setTimeout(() => {
                    onREJECTED(this.result);
                })
            }
            // resolve('这次一定')
        })
    }
}