Promise

一、什么是promise?

1、Promise 是 JS 中进行异步编程的新解决方案
2、从语法上来说: Promise 是一个构造函数
3、从功能上来说: promise 对象用来封装一个异步操作并可以获取其成功/失败的结果值
为什么使用promise?
promise是ES6中用来处理 异步操作 的。如果不使用promise,就需要使用 回调函数来处理异步操作后的结果,此时如果有 多个有顺序 的异步操作,会造成回调的嵌套,引发 回调地狱。
回调地狱的缺点?
1、不便于阅读
2、不便于异常处理

二、promise状态的改变

  1. pending 变为 resolved
  2. pending 变为 rejected
    说明: 只有这 2 种, 且一个 promise 对象只能改变一次

三、promise基本流程

promise

四、基本使用

1、API

  1. Promise 构造函数: Promise (excutor) {}
    (1) executor 函数: 执行器 (resolve, reject) => {}
    (2) resolve 函数: 内部定义成功时我们调用的函数 value => {}
    (3) reject 函数: 内部定义失败时我们调用的函数 reason => {}
    说明: executor 会在 Promise 内部立即同步调用,异步操作在执行器中执行
  2. Promise.prototype.then 方法: (onResolved, onRejected) => {}
    (1) onResolved 函数: 成功的回调函数 (value) => {}
    (2) onRejected 函数: 失败的回调函数 (reason) => {}
    说明: 指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调
    返回一个新的 promise 对象
  3. Promise.prototype.catch 方法: (onRejected) => {}
    (1) onRejected 函数: 失败的回调函数 (reason) => {}
    说明: then()的语法糖, 相当于: then(undefined, onRejected)
  4. Promise.resolve 方法: (value) => {}
    (1) value: 成功的数据或 promise 对象
    说明: 返回一个成功/失败的 promise 对象
  5. Promise.reject 方法: (reason) => {}
    (1) reason: 失败的原因
    说明: 返回一个失败的 promise 对象
  6. Promise.all 方法: (promises) => {}
    (1) promises: 包含 n 个 promise 的数组
    说明: 返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就
    直接失败
  7. Promise.race 方法: (promises) => {}
    (1) promises: 包含 n 个 promise 的数组
    说明: 返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态

2、promise 的几个关键问题

  1. 如何改变 promise 的状态?
    (1) resolve(value): 如果当前是 pending 就会变为 resolved
    (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 的链式调用串连多个同步/异步任务
  6. promise 异常传透?
    (1) 当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调,
    (2) 前面任何操作出了异常, 都会传到最后失败的回调中处理
  7. 中断 promise 链?
    (1) 当使用 promise 的 then 链式调用时, 在中间中断, 不再调用后面的回调函数
    (2) 办法: 在回调函数中返回一个 pendding 状态的 promise 对象

3、代码演示

1、catch

   <script>
       //
       let p = new Promise((resolve, reject) => {
           // ** 同步调用
           // console.log(111);
           //修改 promise 对象的状态
           reject('error');
       });
       // console.log(222);
       //执行 catch 方法
       p.catch(reason => {
           console.log(reason);//error
       });
   </script>

2、resolve()

   <script>
       //如果传入的参数为 非Promise类型的对象, 则返回的结果为成功promise对象
       //如果传入的参数为 Promise 对象, 则参数的结果决定了 resolve 的结果(也为promise对象)
       let p1 = Promise.resolve(521);
       let p2 = Promise.resolve(new Promise((resolve, reject) => {
           // resolve('OK');
           reject('Error');
       }));
       console.log(p2);//rejected--Error,如下图
       p2.catch(reason => {
           console.log(reason);
       })
   </script>

promise
3、reject()

   <script>
       // let p = Promise.reject(521);
       // let p2 = Promise.reject('iloveyou');
       let p3 = Promise.reject(new Promise((resolve, reject) => {
           resolve('OK');
       }));
       //都是返回一个失败的 promise 对象
       console.log(p3);
   </script>

promise
4、all()

   <script>
   //只有所有的 promise 都成功才成功, 只要有一个失败了就直接失败
       let p1 = new Promise((resolve, reject) => {
           resolve('OK');
       })
       // let p2 = Promise.resolve('Success');
       let p2 = Promise.reject('Error');
       let p3 = Promise.resolve('Oh Yeah');
       
       //
       const result = Promise.all([p1, p2, p3]);

       console.log(result);
   </script>

p2为成功promise对象时
promise
p2为一个失败promise对象时,结果为失败时的结果
promise
5、race()

   <script>
       let p1 = new Promise((resolve, reject) => {
           setTimeout(() => {
               resolve('OK');
           }, 1000);
       })
       let p2 = Promise.resolve('Success');
       let p3 = Promise.resolve('Oh Yeah');
       //返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态
       const result = Promise.race([p1, p2, p3]);
       console.log(result);
   </script>

promise
6、Promise 对象状态改变的方式

   <script>
       let p = new Promise((resolve, reject) => {
           //1. resolve 函数
           // resolve('ok'); // pending   => fulfilled (resolved)
           //2. reject 函数
           // reject("error");// pending  =>  rejected 
           //3. 抛出错误
           throw '出问题了';
       });

       console.log(p);
   </script>

promise
7、执行多个回调

   <script>
       let p = new Promise((resolve, reject) => {
           resolve('OK');
       });

       ///指定回调 - 1
       p.then(value => {
           console.log(value);
       });

       //指定回调 - 2
       p.then(value => {
           alert(value);
       });
   </script>

8、then的返回结果

   <script>
       let p = new Promise((resolve, reject) => {
           resolve('ok');
       });
       //执行 then 方法
       let result = p.then(value => {
           // console.log(value);
           //1. 抛出错误
           // throw '出了问题';
           //2. 返回结果是非 Promise 类型的对象
           // return 521;
           //3. 返回结果是 Promise 对象
           // return new Promise((resolve, reject) => {
           //     // resolve('success');
           //     reject('error');
           // });
       }, reason => {
           console.warn(reason);
       });

       console.log(result);
   </script>

1.promise
2.
promise

promise
9、Promise串联多个任务

 <script>
     let p = new Promise((resolve, reject) => {
         setTimeout(() => {
             resolve('OK');
         }, 1000);
     });

     p.then(value => {
         return new Promise((resolve, reject) => {
             resolve("success");
         });
     }).then(value => {
         console.log(value);
     }).then(value => {
         console.log(value);
     })
 </script>

promise
10、异常穿透现象

 <script>
     let p = new Promise((resolve, reject) => {
         setTimeout(() => {
             resolve('OK');
             // reject('Err');
         }, 1000);
     });

     p.then(value => {
         // console.log(111);
         throw '失败啦!';
     }).then(value => {
         console.log(222);
     }).then(value => {
         console.log(333);
     }).catch(reason => {
         console.warn(reason);
     });
 </script>

promise
11、中断promise链条

 <script>
     let p = new Promise((resolve, reject) => {
         setTimeout(() => {
             resolve('OK');
         }, 1000);
     });

     p.then(value => {
         console.log(111);
         //有且只有一个方式
         return new Promise(() => {});
     }).then(value => {
         console.log(222);
     }).then(value => {
         console.log(333);
     }).catch(reason => {
         console.warn(reason);
     });
 </script>

五、promise自定义封装

//声明构造函数
function Promise(executor){
    //添加属性
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    //声明属性
    this.callbacks = [];
    //保存实例对象的 this 的值
    const self = this;// self _this that
    //resolve 函数
    function resolve(data){
        //判断状态
        //这里this是windows,所以在外面保存实例对象this
        if(self.PromiseState !== 'pending') return;
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'fulfilled';// resolved
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
        //调用成功的回调函数
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onResolved(data);
            });
        });
    }
    //reject 函数
    function reject(data){
        //判断状态
        if(self.PromiseState !== 'pending') return;
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'rejected';// 
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
        //执行失败的回调
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onRejected(data);
            });
        });
    }
    try{
        //同步调用『执行器函数』
        executor(resolve, reject);
    }catch(e){
        //修改 promise 对象状态为『失败』
        reject(e);
    }
}

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
    const self = this;
    //判断回调函数参数
    if(typeof onRejected !== 'function'){
        onRejected = reason => {
            throw reason;
        }
    }
    if(typeof onResolved !== 'function'){
        onResolved = value => value;
        //value => { return value};
    }
    return new Promise((resolve, reject) => {
        //封装函数
        function callback(type){
            try{
                //获取回调函数的执行结果
                let result = type(self.PromiseResult);
                //判断
                if(result instanceof Promise){
                    //如果是 Promise 类型的对象
                    result.then(v => {
                        resolve(v);
                    }, r=>{
                        reject(r);
                    })
                }else{
                    //结果的对象状态为『成功』
                    resolve(result);
                }
            }catch(e){
                reject(e);
            }
        }
        //调用回调函数  PromiseState
        if(this.PromiseState === 'fulfilled'){
            //then异步执行
            setTimeout(() => {
                callback(onResolved);
            });
        }
        if(this.PromiseState === 'rejected'){
            setTimeout(() => {
                callback(onRejected);
            });
        }
        //判断 pending 状态
        //当new promise时,设置了异步函数setTimeout,此时PromiseState仍然为pending
        if(this.PromiseState === 'pending'){
            //保存回调函数
            this.callbacks.push({
                onResolved: function(){
                    callback(onResolved);
                },
                onRejected: function(){
                    callback(onRejected);
                }
            });
        }
    })
}

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

//添加 resolve 方法
Promise.resolve = function(value){
    //返回promise对象
    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(promises){
    //返回结果为promise对象
    return new Promise((resolve, reject) => {
        //声明变量
        let count = 0;
        let arr = [];
        //遍历
        for(let i=0;i<promises.length;i++){
            //
            promises[i].then(v => {
                //得知对象的状态是成功
                //每个promise对象 都成功
                count++;
                //将当前promise对象成功的结果 存入到数组中
                arr[i] = v;
                //判断
                if(count === promises.length){
                    //修改状态
                    resolve(arr);
                }
            }, r => {
                reject(r);
            });
        }
    });
}

//添加 race 方法
Promise.race = function(promises){
    return new Promise((resolve, reject) => {
        for(let i=0;i<promises.length;i++){
            promises[i].then(v => {
                //修改返回对象的状态为 『成功』
                resolve(v);
            },r=>{
                //修改返回对象的状态为 『失败』
                reject(r);
            })
        }
    });
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值