关于javascript:Promise从入门到精通

Promise从入门到精通

概念

Promise是ES6引入的进行异步编程的新的解决方案

备注:旧计划是单纯的应用回调函数

  • 从语法上来说:它就是一个构造函数,
  • 从性能上来说:能够封装异步的工作,并且能够对后果进行解决

Promise最大的益处:能够解决回调天堂的问题,并且它在指定回调和错误处理这一块更加的灵便与不便

回调天堂的典型情景:

异步编程有哪些?

答:fs文件操作、数据库操作、AJAX、定时器等等

为什么要应用Promise?

  1. 指定回调函数的形式更加灵便
    旧的形式:必须在启动异步工作前指定

    ·promise:启动异步工作 => 返回promise对象 => 给promise对象绑定回调函数(甚至能够在异步工作完结后指定多个回调)

  2. 反对链式调用,能够解决回调天堂问题

    回调天堂的毛病:1)不便于浏览;2)不便于异样解决

Promise的根本流程

promise的状态扭转

​ 状态指的是promise实例中的一个属性:【PromiseState】

​ pending 未决定的

​ fulfilled 胜利

​ rejected 失败

​ 1. pending => fulfilled

​ 2. pending => rejected

​ promise对象的状态只有这两种扭转,1个promise对象的状态只能扭转一次,

​ 不可能由fulfilled转rejected

​ 也不可能由rejected转fulfilled

promise对象后果值属性介绍

​ 实例对象中另一个属性:【PromiseResult】

​ 保留的是胜利/失败的后果

​ resolve能够批改PromiseResult的值

​ rejected能够批改PromiseResult的值

如何应用Promise?

​ API

1.Promise构造函数:Promise(exector){}

​ 1)exector函数:称为执行器函数 (resolve,reject)=>{}

​ 2)resolve函数:是Promise外部定义的,胜利时咱们调用resolve函数

​ 3)reject函数:是Promise外部定义的,失败时咱们调用reject函数

​ 阐明:exector会在Promise外部立刻同步调用,异步操作在执行器中执行

2.Promise.prototype.then办法:(onResolved,onRejected)=>{}

​ 1)onResolved函数:指定胜利的回调函数 value=>{}

​ 2)onRejected函数:指定失败的回调函数 reason=>{}

​ 阐明:指定用于失去胜利value的胜利回调和用于失去失败reason的失败回调,返回一个新的promise对象

3.Promise.prototype.catch办法:(onRejected)=>{}

​ onRejected函数:指定失败的回调函数 reason=>{}

​ 阐明:then()的语法糖,相当于then(undefined,onRejected)

4.Promise.resolve办法 (value)=>{}

​ 1)value:胜利的数据或promise对象

​ 阐明:返回一个胜利/失败的promise对象

​ 作用:为了疾速失去一个promise对象,而且可能封装1个值,将这个值转化为promise对象

​ 如果传入的参数为非promise类型的对象,则返回的后果为胜利的promise对象

​ 如果传入的参数为promise对象,则参数的后果决定了resolve的后果

5.Promise.reject办法:(reason)=>{}

​ 作用:疾速返回一个失败的promise对象

​ 返回的后果永远都是失败的promise对象

6.Promise.all办法:(promises数组)=>{}

​ 参数:蕴含n个promise的数组

​ 阐明:返回一个新的promise对象,只有所有的promise都胜利才胜利,只有有一个失败就间接失败

7.Promise.race办法:(promises数组)=>{}

​ race有赛跑的意思

​ 参数:蕴含n个promise的数组

​ 阐明:返回一个新的promise对象,第一个扭转状态的promise就是最终的后果状态

promise的几个关键问题

​ 1. 如何扭转promise的状态?

​ (1) resolve(value): 如果以后是pending就会变为fulfilled

​ (2) reject(reason): 如果以后是pending就会变为rejected

​ (3) 抛出异样: 如果以后是pending就会变为rejected

​ 2. 一个promise指定多个胜利/失败回调函数, 都会调用吗?

​ 当promise扭转为对应状态时都会调用

​ 3. 扭转promise状态和指定回调函数谁先谁后?

​ (1) 都有可能, 失常状况下是先指定回调再扭转状态, 但也能够先改状态再指定回调

​ (2) 如何先改状态再指定回调?

​ ① 在执行器中间接调用resolve()/reject()

​ ② 提早更长时间才调用then()

​ (3) 什么时候能力失去数据?

​ ① 如果先指定的回调, 那当状态产生扭转时, 回调函数就会调用, 失去数据

​ ② 如果先扭转的状态, 那当指定回调时, 回调函数就会调用, 失去数据

​ 4. promise.then()返回的新promise的后果状态由什么决定?

​ (1) 简略表白: 由then()指定的回调函数执行的后果决定

​ (2) 具体表白:

​ ① 如果抛出异样, 新promise变为rejected, reason为抛出的异样

​ ② 如果返回的是非promise的任意值, 新promise变为resolved, value为返回的值

​ ③ 如果返回的是另一个新promise, 此promise的后果就会成为新promise的后果

​ 5. promise如何串连多个操作工作?

​ (1) promise的then()返回一个新的promise, 能够开成then()的链式调用

​ (2) 通过then的链式调用串连多个同步/异步工作

let p = new Promise((resolve,reject)=>{

  setTimeout(()=>{

    resolve('ok');

  },1000);

});



p.then(v=>{

  return new Promise((resolve,reject)=>{

    resolve('success');

  });

}).then(v=>{

  console.log(v);

}).then(v=>{

  console.log(v);

})

​ 6. promise异样传透?

​ (1) 当应用promise的then链式调用时, 能够在最初指定失败的回调,

​ (2) 后面任何操作出了异样, 都会传到最初失败的回调中解决

let p = new Promise((resolve,reject)=>{

  reject('err');

});



p.then(v=>{

  console.log(111);

}).then(v=>{

  console.log(222);

}).then(v=>{

  console.log(333);

}).catch(r=>{

  console.log(r);

});

​ 7. 中断promise链?

​ (1) 当应用promise的then链式调用时, 在两头中断, 不再调用前面的回调函数

​ (2) 方法: 在回调函数中返回一个pendding状态的promise对象

代码展现

//申明函数        执行器   『同步回调』

function Promise(executor) {
    //设置实例对象的属性
    this.PromiseState = 'pending';
    this.PromiseResult = undefined;
    this.callbacks = [];

    //申明函数
    const success = (value) => {
        if (this.PromiseState !== 'pending') return;
        //批改状态为胜利  PromiseState
        this.PromiseState = 'fulfilled';
        //设置胜利的后果值 PromiseResult
        this.PromiseResult = value;
        //调用回调
        if (this.callbacks.length > 0) {
            this.callbacks.forEach(cbObj => {
                //执行胜利的回调
                cbObj.ok();
            })
        }
    }

    const fail = (reason) => {
        if (this.PromiseState !== 'pending') return;
        //批改状态为失败  PromiseState
        this.PromiseState = 'rejected';
        //设置胜利的后果值 PromiseResult
        this.PromiseResult = reason;
        //调用回调
        if (this.callbacks.length > 0) {
            this.callbacks.forEach(cbObj => {
                //执行胜利的回调
                cbObj.ng();
            })
        }
    }

    try {
        //调用执行器函数
        executor(success, fail);
    } catch (e) {
        //调用 fail 函数
        fail(e);
    }
}

Promise.prototype.then = function (onFulfilled, onRejected) {

    //判断  异样穿透
    if(typeof onRejected !== 'function'){
        onRejected = reason => {throw reason};
    }

    //值传递
    if(typeof onFulfilled !== 'function'){
        onFulfilled = value => value;
    }

    return new Promise((resolve, reject) => {
        //封装函数简化代码
        let callback = (type) => {
            try {
                let res = type(this.PromiseResult);
                //判断
                if (res instanceof Promise) {
                    res.then(v => {
                        resolve(v);
                    }, r => {
                        reject(r);
                    })
                } else {
                    resolve(res);
                }
            } catch (e) {
                reject(e);
            }
        }

        //判断 胜利
        if (this.PromiseState === 'fulfilled') {
            setTimeout(() => {
                callback(onFulfilled);// 
            })
        }

        //失败
        if (this.PromiseState === 'rejected') {
            setTimeout(() => {
                callback(onRejected);
            })
        }

        //pending 
        if (this.PromiseState === 'pending') {
            //保留回调
            this.callbacks.push({
                ok: function () {
                    //胜利
                    callback(onFulfilled);
                },
                ng: function () {
                    callback(onRejected);
                }
            })

        }

    });
}

Promise.prototype.catch = function(onRejected){
    return this.then(undefined, onRejected);
}

Promise.resolve = function(value){
    return new Promise((resolve,reject) => {
        //判断
        if(value instanceof Promise){
            //value.then(resolve, reject); 这行代码和上面5行代码性能一样
            value.then(v=>{
                resolve(v);
            }, r => {
                reject(r);
            });
        }else{
            resolve(value);
        }
    })
}

Promise.reject = function(reason){
    return new Promise((resolve, reject) => {
        reject(reason);
    })
}


Promise.all = function (promiseArr) {
    return new Promise((resolve, reject) => {
        let count = 0;
        let arr = [];
        for (let i = 0; i < promiseArr.length; i++) {
            promiseArr[i].then(v => {
                count++;
                arr[i] = v;
                if (count === promiseArr.length) {
                    resolve(arr);
                }
            }, r => {
                reject(r);
            });
        }
    });
}


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

面试题1:

let p = new Promise((resolve, reject) => {
    reject("error");
});

p.then(v => {
    console.log(v);
}).then(v => {
    console.log(v);
}, r => {
    console.log(r); // error
}).then(v => {
    console.log(v);  // undefined
}, r => {
    console.warn(r); 
});

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理