【手写Promise】

一、JS的错误

1、错误的类型

2、错误处理

3、错误对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        //1、错误类型
        // ReferenceError:引用的变量不存在
        // TypeError:数据类型不正确,b.xxx错误在b
        // RangeError:数据值不在允许范围内
        // SyntaxError:语法错误

        //2、错误处理
        //捕获错误:try...catch
        //抛出错误:throw error

        //3、错误对象
        // message:错误相关信息
        // stack属性:函数调用栈记录信息

        //本身知道异常是什么,不需要自己定义异常
        try {
            let d;
            console.log(d.xxx);
            //从前面接到error
        } catch (error){
            console.log(error.message);
            console.log(error.stack);
        }

        //不知道异常如何抛出,需要自己定义异常
        function time(){
            if(Date.now()%2 ==1){
                console.log('奇数时间没问题');
            }else{
                throw new Error('偶数时间有问题')
            }
        }
        try {
            time()
        } catch (error) {
            console.log(error.message);
        }
    </script>
</body>
</html>

二、Promise介绍

JS中进行异步编程的新的解决方案;

语法上是一个构造函数,功能上是一个对象来封装异步操作并可以获得结果。

1、promise状态pending

promise状态只能改变一次,只有一个结果数据

pending----->resolved::成功数据value

pending----->rejected::失败原因reason
【手写Promise】_第1张图片

2、Promise基本使用

先同步任务----- new promise实例对象—启动异步任务----返回promise对象-----给promise对象绑定回调函数------甚至可以在异步之后再绑定回调

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        const p = new Promise((resolve,rejecte)=>{   //执行器函数先执行(同步任务),再new Promise(),启动异步任务
            //异步函数
            setTimeout(() => {
                if(Date.now()%2 == 0){
                    resolve('成功')  //value
                }else{
                    rejecte('失败')  //reason
                }
            }, 1000);
        })
        p.then(
            //onResolve
            //此处的value是从异步函数中获取到的成功的返回值
            (value)=>{
                console.log(value);
            },
            //onRejected
            //此处的reason是从异步函数中获取到的失败的原因
            (reason)=>{
                console.log(reason);
            }
        ) 
    </script>
</body>
</html>

3、新旧区别--------解决回调地狱

旧的:必须在启动异步任务之前指定好成功、失败的回调

新的:可以启动异步任务,甚至结束异步任务后,再指定回调

三、深度使用Promise

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <script>
        new Promise((resolve,reject)=>{
            setTimeout(() => {
                // resolve('成功回调');
                reject('失败的回调')
            }, 1000);
        }).then(
            (value) =>{
                console.log(value);
            }
        ).catch(
            (reason)=>{
                console.log(reason);
            }
        )
        //产生一个值为1的成功的promise
        const p1 = Promise.resolve(1);
        p1.then(
            value =>{
                console.log(value);
            }
        )
        //产生一个值为2的失败的promise
        const p2 = Promise.reject(2);
        p2.catch(
            reason =>{
                console.log(reason);
            }
        )
        // Promise.all必须所有的都有成功的回调,返回的是成功的数据,才算成功;如果失败需要返回失败的原因
        const pAll = Promise.all([p1,p2,p3])
        // Promise.race看谁先完成,会返回第一个成功的和第一个失败的
        const pRace = Promise.race();
    script>
body>
html>
几个问题:

1、多个then,可以全部执行,

2、先有回调函数 .the,但是状态没改,保存好;后改变状态(并且指定数据),调用函数

​ 先改变状态(并且指定数据),调用函数;;后有回调函数 .the,并异步调用

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <script>
        new Promise((resolve,reject)=>{
            resolve('成功回调')
        }).then(
            //异步执行
            value =>{
                console.log(value);
            },
            reason =>{
                console.log(reason);
            }
        );
        console.log('--------');
        // --------
        // 成功回调
        console.log('--------');
        //.then之后是一个新的Promise,根据新Promise的状态,来判断之后的.then
        new Promise((resolve,reject)=>{
            resolve('成功回调')
        }).then(
            //异步执行
            value =>{
                console.log('onResolved1',value); //onResolved1,成功回调
                return 2          //此时会返回2
                return Promise.resolve(3);      //返回3
                throw 4;          //传递给下面的onRejected2
            },
            reason =>{
                console.log('onResolved2',reason);
            }
        ).then(
            //异步执行
            value =>{
                console.log('onResolved2',value);     //undefined     //2
            },
            reason =>{
                console.log('onRejected2',reason);
            }
        );
    script>
body>
html>
异常穿透和中断Promise链
//层层穿透
Promise.then.then.catch
//中断Promise链
return new Promise(()=>{})

四、自定义Promise,手写

/*
自定义Promise函数模块:IIFE
 */
(function(window){
    //Promise构造函数
    //executor执行器函数
     function Promise(executor){
         //执行器函数,会立即执行
         function resolve(){

         }
         function reject() {

         }
         //传入的参数为两个函数
         executor(resolve,reject)
     }
     /* 
     //.then接收成功失败的回调
     返回新的Promise
      */
     Promise.prototype.then = function(onResolved,onRejected){

     }
     /*
     接收失败的回调
     返回新的promise
      */
     Promise.prototype.catch = function(onRejected){

     }
     /* 
     promise函数对象的resolve方法
     */
     Promise.resolve = function(value){

     }
    /*
     promise函数对象的reject方法
     */
     Promise.reject = function(reason){

     }
     //all接收数组
     Promise.all = function(promises){

     }
     //race接收数组
     Promise.race = function(promise){

     }
})(window)

五、async和await的使用

1、async函数:返回值是promise对象,结果由返回值决定

2、await表达式:右侧一般是promise对象,也可为其它;若为promise,则返回成功值,

3、await必须写在async的函数中,async函数可以无await;如果await的promise失败,用try catch来抛出异常

六、JS异步之宏队列与微队列

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <script>
        // 3,4,0,1,2
        //执行函数队列又分为宏与微,每执行新的一个宏之前,都要去微里面看看是否还有函数
          setTimeout(() => {
              console.log(0);
              Promise.resolve(1).then(value =>{
                  console.log(value);
              })
          }, 1000);
          setTimeout(() => {
              console.log(2);
          }, 1000);
          Promise.resolve(3).then(value=>{
              console.log(value);
          })
          Promise.resolve(4).then(value =>{
            console.log(value);
          })
          
    script>
body>
html>

七、手写promise(函数)

/*
自定义Promise函数模块:IIFE
 */
(function(window){
    const PENDING = 'pending';
    const RESOVLED = 'resolved';
    const REJECTED = 'rejected';
    //Promise构造函数
    //executor执行器函数
     function Promise(executor){
         let that = this;
         this.status = PENDING;   //状态未变之前都是pending
         this.data = undefined;     //未定义的数据
         this.callbacks = [];       //每个元素的结构:onResolved(){},onRejected(){}
         //执行器函数,会立即执行
         //两个改变promise状态的函数
         function resolve(value){
             if(that.status!==PENDING) return
             //调用resolve后,需要将状态改变成为resolved
             that.status = RESOVLED;
             //保存data数据
             that.data= value;
             //如果有未执行的callback,则立即异步执行onResolved,是包含两个回调的对象
             if(that.callbacks.length>0){
                 setTimeout(() => {
                    that.callbacks.forEach(element => {
                        element.onResolved(value)
                    });
                 });
             }
         }
         function reject(reason) {
            if(that.status!==PENDING) return
              //调用reject后,需要将状态改变成为rejected
              that.status = REJECTED;
              //保存data数据
              that.data= reason;
              //如果有未执行的callback,则立即异步执行onRejected,是包含两个回调的对象
              if(that.callbacks.length>0){
                  setTimeout(() => {
                    that.callbacks.forEach(element => {
                         element.onResolved(reason)
                     });
                  });
              }
         }
         //传入的参数为两个函数
         //除了resolve和reject,还有可能自己抛出异常,会失败,此时需要一个try catch
         try {
            executor(resolve,reject)
         } catch (error) {
             reject(error);
         }
     }
     /* 
     //.then接收成功失败的回调
     返回新的Promise
      */
     Promise.prototype.then = function(onResolved,onRejected){
         const that = this;
         // 指定回调函数的默认值(必须是函数)
         onResolved = typeof onResolved === 'function'?onResolved:value =>value  //继续向下传递
         onRejected = typeof onRejected ==='function'? onRejected:reason =>{throw reason}  //抛出异常
         return new Promise((resolve,reject) =>{
            function handle(callback){
                try {
                    const result = onResolved(that.data)
                    if(result instanceof Promise){
                        result.then(resolve,reject
                            // value =>{
                            //     resolve(value)
                            // },
                            // reason=>{
                            //     reject(reason)
                            // }
                        )
                    }
                } catch (error) {
                    reject(error);
                }
            }

            if(this.status ===PENDING){
            //假设当前状态还是pending,将回调保存下来
            this.callbacks.push({
                onResolved(value){
                    handle(onResolved)
                },
                onRejected(reason){
                    handle(onRejected)
                }
            })
            }else if(this.status ===RESOVLED){
                setTimeout(() => {
                //  如果回调是promise,return的promise结果就是这个promise结果
                handle(onResolved)
                });
            }else{
                //如果前面的promise返回的是失败的回调
                setTimeout(() => {
                    handle(onRejected)
                    });
            }
         })
     }
     /*
     接收失败的回调
     返回新的promise
      */
    Promise.prototype.catch = function(onRejected){
        return this.then(undefined,onRejected)
    }
    /*
    promise函数对象的resolve方法
     */
    Promise.resolve = function(value){
        return new Promise((resolve,reject) =>{
            if(value instanceof Promise){
                value.then(resolve,reject)
            }else{
                resolve(value);
            }
        })
    }
    /*
    promise函数对象的reject方法
     */
    Promise.reject = function(reason){
        return new Promise((resolve,reject) =>{
            reject(reason)
    })
    }
     //all接收数组
    Promise.all = function(promises){
        const values = [];
        const resolvedCount = 0;
        return new Promise((resolve,reject)=>{
             //遍历promise获取每个promise的结果
            promises.forEach((p,index) =>{
                Promise.resolve(p).then(
                     //成功的时候需要放入数组中
                    value => {
                         resolvedCount++;
                         values[index] = value;
                         if(resolvedCount == promises.length){
                             resolve(values);
                         }
                    },
                    reason =>{
                        //只要一个失败了,return的promise就失败
                        reject(reason)
                    }
                )
            })
        })
    }
     //race接收数组
    Promise.race = function(promise){
        //返回一个pomise
        return new Promise((resolve,reject) =>{
            Promise.resolve(p).then(
                //一旦有成功,return成功
                value =>{
                    resolve(value);
                },
                //一旦有失败,return失败
                reason =>{
                    reject(reason)
                }
            )
        })
    }

    // promise的resolveDelay,rejectDelay
/* promise函数对象的resolveDelay方法
*/ 
Promise.resolveDelay = function(value,time){
    return new Promise((resolve,reject) =>{
        setTimeout(() => {
         if(value instanceof Promise){
             value.then(resolve,reject)
         }else{
             resolve(value);
         }
        }, time);
    })
 }
 /*
 promise函数对象的rejectDelay方法
 */
 Promise.rejectDelay = function(reason,time){
    return new Promise((resolve,reject) =>{
        setTimeout(() => {
         reject(reason)
        }, time);
 })
 }
})(window)

手写promise(类)

/*
自定义Promise函数模块:IIFE
 */
(function(window){
    const PENDING = 'pending';
    const RESOVLED = 'resolved';
    const REJECTED = 'rejected';

    class Promise {
        constructor(executor){
        let that = this;
         this.status = PENDING;   //状态未变之前都是pending
         this.data = undefined;     //未定义的数据
         this.callbacks = [];       //每个元素的结构:onResolved(){},onRejected(){}
         //执行器函数,会立即执行
         //两个改变promise状态的函数
         function resolve(value){
             if(that.status!==PENDING) return
             //调用resolve后,需要将状态改变成为resolved
             that.status = RESOVLED;
             //保存data数据
             that.data= value;
             //如果有未执行的callback,则立即异步执行onResolved,是包含两个回调的对象
             if(that.callbacks.length>0){
                 setTimeout(() => {
                    that.callbacks.forEach(element => {
                        element.onResolved(value)
                    });
                 });
             }
         }
         function reject(reason) {
            if(that.status!==PENDING) return
              //调用reject后,需要将状态改变成为rejected
              that.status = REJECTED;
              //保存data数据
              that.data= reason;
              //如果有未执行的callback,则立即异步执行onRejected,是包含两个回调的对象
              if(that.callbacks.length>0){
                  setTimeout(() => {
                    that.callbacks.forEach(element => {
                         element.onResolved(reason)
                     });
                  });
              }
         }
         //传入的参数为两个函数
         //除了resolve和reject,还有可能自己抛出异常,会失败,此时需要一个try catch
         try {
            executor(resolve,reject)
         } catch (error) {
             reject(error);
         }
        }
             /* 
     //.then接收成功失败的回调
     返回新的Promise
      */
     then (onResolved,onRejected){
        const that = this;
        // 指定回调函数的默认值(必须是函数)
        onResolved = typeof onResolved === 'function'?onResolved:value =>value  //继续向下传递
        onRejected = typeof onRejected ==='function'? onRejected:reason =>{throw reason}  //抛出异常
        return new Promise((resolve,reject) =>{
           if(this.status ===PENDING){
           //假设当前状态还是pending,将回调保存下来
           this.callbacks.push({
               onResolved(value){
                   onResolved(that.data);
                   try {
                       const result = onResolved(that.data)
                       if(result instanceof Promise){
                           result.then(resolve,reject
                               // value =>{
                               //     resolve(value)
                               // },
                               // reason=>{
                               //     reject(reason)
                               // }
                           )
                       }
                   } catch (error) {
                       resolve(error);
                   }
               },
               onRejected(reason){
                   onRejected(that.data);
                   try {
                       const result = onRejected(that.data)
                       if(result instanceof Promise){
                           result.then(resolve,reject
                               // value =>{
                               //     resolve(value)
                               // },
                               // reason=>{
                               //     reject(reason)
                               // }
                           )
                       }
                   } catch (error) {
                       reject(error);
                   }
               }
           })
           }else if(this.status ===RESOVLED){
               setTimeout(() => {
               //  如果回调是promise,return的promise结果就是这个promise结果
               try {
                   const result = onResolved(that.data)
                   if(result instanceof Promise){
                       result.then(resolve,reject
                           // value =>{
                           //     resolve(value)
                           // },
                           // reason=>{
                           //     reject(reason)
                           // }
                       )
                   }else{//返回的不是promise,返回promise为成功,value就是返回值
                       resolve(result)
                   }
               } catch (error) {
                   reject(error);
               }
               });
           }else{
               //如果前面的promise返回的是失败的回调
               setTimeout(() => {
                   //  如果回调是promise,return的promise结果就是这个promise结果
                   try {
                       const result = onRejected(that.data)
                       if(result instanceof Promise){
                           result.then(resolve,reject
                               // value =>{
                               //     resolve(value)
                               // },
                               // reason=>{
                               //     reject(reason)
                               // }
                           )
                       }
                   } catch (error) {
                       try {
                   const result = onResolved(that.data)
                   if(result instanceof Promise){
                       result.then(resolve,reject
                           // value =>{
                           //     resolve(value)
                           // },
                           // reason=>{
                           //     reject(reason)
                           // }
                       )
                   }
               } catch (error) {
                   reject(error);
               }
                   }
                   });
           }
        })
    }
    /*
    接收失败的回调
    返回新的promise
     */
   catch (onRejected){
       return this.then(undefined,onRejected)
   }
   /*
   promise函数对象的resolve方法
    */
   static resolve(value){
       return new Promise((resolve,reject) =>{
           if(value instanceof Promise){
               value.then(resolve,reject)
           }else{
               resolve(value);
           }
       })
   }
   /*
   promise函数对象的reject方法
    */
   static reject(reason){
       return new Promise((resolve,reject) =>{
           reject(reason)
   })
   }
    //all接收数组
   static all(promises){
       const values = [];
       const resolvedCount = 0;
       return new Promise((resolve,reject)=>{
            //遍历promise获取每个promise的结果
           promises.forEach((p,index) =>{
               Promise.resolve(p).then(
                    //成功的时候需要放入数组中
                   value => {
                        resolvedCount++;
                        values[index] = value;
                        if(resolvedCount == promises.length){
                            resolve(values);
                        }
                   },
                   reason =>{
                       //只要一个失败了,return的promise就失败
                       reject(reason)
                   }
               )
           })
       })
   }
    //race接收数组
   static race (promise){
       //返回一个pomise
       return new Promise((resolve,reject) =>{
           Promise.resolve(p).then(
               //一旦有成功,return成功
               value =>{
                   resolve(value);
               },
               //一旦有失败,return失败
               reason =>{
                   reject(reason)
               }
           )
       })
   }

   // promise的resolveDelay,rejectDelay
/* promise函数对象的resolveDelay方法
*/ 
static resolveDelay (value,time){
   return new Promise((resolve,reject) =>{
       setTimeout(() => {
        if(value instanceof Promise){
            value.then(resolve,reject)
        }else{
            resolve(value);
        }
       }, time);
   })
}
/*
promise函数对象的rejectDelay方法
*/
static rejectDelay (reason,time){
   return new Promise((resolve,reject) =>{
       setTimeout(() => {
        reject(reason)
       }, time);
})
}
    }})(window)

你可能感兴趣的:(javascript,前端,vue.js)