ES6中 Promise()对象,Promise.all()方法,Promise.race() 方法,async 函数

回调地狱

回调地狱: 因为js是单线程的, 有些时候为了代码功能需求,需要函数嵌套函数,当函数嵌套多层时,就会形成回调地狱

如何解决回调地狱: 通过Promise() 解决

模拟异步操作

  <script>
  //  模拟异步操作  (下面例子当调用函数fun2()执行顺序  2 1  3)
        function fun1(){
    
    
            setTimeout(function(){
    
    
                console.log('setTimeout1');      
                fun3()          
            }, 1000)
        }
        function fun2(){
    
    
            setTimeout(function(){
    
    
                console.log('setTimeout2');    
                fun1()            
            }, 2000)
        }
        function fun3(){
    
    
            setTimeout(function(){
    
    
                console.log('setTimeout3');               
            }, 2000)
        }
        fun2();//输出顺序   2   1  3
   </script>

回调地狱实例

 function fun() {
    
    

            setTimeout(function () {
    
    

                console.log(2);

                setTimeout(function () {
    
    

                    console.log(1);

                    setTimeout(function () {
    
    

                        console.log(3);

                    })
                })                
            })
        }
       fun();  执行顺序是  2  1   3

Promise() 对象

Promise() 对象:
存在三种状态:

  • 进行时 pending

  • 成功 resolve

  • 失败 reject

    状态的改变 只能从 pending 转换为 resolve; 或者 从pending 转换为 reject; 如果处于pending状态,永远不知道下一步转换为什么状态

    Promise() 接受一个函数作为参数; 函数存在两个参数(这两个参数是js原生提供的) 一个是resolve, 一个是reject

Promise()的执行机制
如果Promise()执行成功,则会调用执行 resolve(); resolve()中的参数就是执行成功的结果,通过then() 进行接受, then() 参数是一个函数,函数的参数就是 resolve传递传递出来的数据

如果Promise()执行失败, 则会调用执行 reject(); reject()中的参数就是执行失败的错误信息, 通过 catch()进行接受, catch的参数一个函数。 函数的参数 err 就是reject 传递出来的错误信息

上实例

<script> 
    var p1 = new Promise(function(resolve, reject){
    
    
        if(Math.random() > 0.5){
    
    //二分之一的概率成功或失败
            //  执行成功
            // resolve() 会自动调用 then() 中的回调函数, resolve()的参数(数据)就是 then() 中回调函数的接受的数据
            resolve('  成功的结果');
        }else{
    
    
            //  执行失败
            // reject() 会自动调用 catch()中的回调函数, reject()的参数(错误信息) 就是catch()中的回调函数接受的数据
            reject('  失败的信息')
        }
    })
    p1.then(function(data){
    
    
        console.log('promise 成功执行了' + data);  // promise 成功执行了  成功的结果
    }).catch(function(err){
    
    
        console.log('promise 执行失败' + err);  // promise 执行失败  失败的信息
    })
</script>

官方解释

resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

Promise()基本结构:
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数; 因为这样, 可以通过Promise() 解决回调地狱的问题

Promise.all()方法

10个ajax请求 全部执行结束 然后在去做下一件事情 ; 如何判断10个请求都执行完成结束了呢?

Promise.all() 方法可以解决这个问题:
接受的参数是一个数组, 数组中的每个值是promise 实例对象, all()的状态是由参数的状态的决定 ; 所有的promise对象都成功则成功,有一个失败则失败

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。(返回的结果是一个新的Promise()对象)

    <script>
        function fun1() {
    
    
            return new Promise((resolve, reject) => {
    
    
                setTimeout(() => {
    
    
                    console.log('setTimeout1');
                 resolve('setTimeout1 的 data');
                }, 1000)
            })
        }
        function fun2() {
    
    
            return new Promise((resolve, reject) => {
    
    
                setTimeout(() => {
    
    
                   console.log('setTimeout2');
                    resolve('setTimeout2 的 data2');
                }, 1500)
            })
        }
        function fun3() {
    
    
            return new Promise((resolve, reject) => {
    
    
                setTimeout(() => {
    
    
                   console.log('setTimeout3');
                    resolve('setTimeout3 的 data3');
                }, 2000)
            })
        }
        //  Promise.all() 参数是一个数组, 数组中的每个值都是Ppromise()的实例对象,这里也算是调用 
        const p = Promise.all([fun1(), fun2(), fun3()]);
        //  p 的状态 有 fun1(), fun2(), fun3() 决定,只有fun1(), fun2(), fun3() 都是成功,则 p的 状态是 成功 fulfilled ; 如果  fun1(), fun2(), fun3() 存在一个失败,则 p的状态 是失败rejected
        console.log(p);
        p.then((data) => {
    
    
            //  then()方法的回调函数的参数 是 所有 Promise()实例执行成功时传递的数据,自动把所有的数据放到一个数组中
            console.log(data);// (3) ["setTimeout1 的 data", "setTimeout2 的 data2", "setTimeout3 的 data3"]
            console.log('三个函数都执行结束');            
        }).catch((err) => {
    
    
            //  catch() 方法 优先捕获失败的信息, 谁先失败 就捕获谁 
            console.log(err);
        });
    </script>

看输出代码
在这里插入图片描述

我们让其一个值状态为失败,看下是不是这样呢

function fun2() {
    
    
            return new Promise((resolve, reject) => {
    
    
                setTimeout(() => {
    
    
                   console.log('setTimeout2');  
                    reject('setTimeout2 的 data2');
                }, 1500)
            })
        }

在这里插入图片描述

Promise.race() 方法

Promise.race() 方法 的参数是一个数组, 数组中的每个值是 Promise() 实例对象; 最后返回一个新的Promise() 对象
状态 改变: fun1(), fun2(), fun3() 三个实例对象 谁的状态先改变(不管成功还是失败),则p的状态都会随之跟随改变 如果fun1(), fun2(), fun3() 三个实例对象 先改变的状态是成功,则成功,如果失败就是失败

<script>
    function fun1() {
    
    
        return new Promise((resolve, reject) => {
    
    
            setTimeout(() => {
    
    
                console.log('setTimeout1');
              // resolve('setTimeout1 的 data1  成功');
                 reject('setTimeout1 第一个失败');//因为fun1()的状态先改变失败,所以为失败
            }, 1000)
        })
    }
    function fun2() {
    
    
        return new Promise((resolve, reject) => {
    
    
            setTimeout(() => {
    
    
                console.log('setTimeout2');
               resolve('setTimeout2 的 data2  成功');
              //  reject('setTimeout2 的 失败');
            }, 1500)
        })
    }
    function fun3() {
    
    
        return new Promise((resolve, reject) => {
    
    
            setTimeout(() => {
    
    
                console.log('setTimeout3');
               // resolve('setTimeout3 的 data3  成功');
                reject('setTimeout3 失败了');
            }, 2000)
        })
    }
    //  Promise.race() 方法 的参数是一个数组, 数组中的每个值是 Promise() 实例对象; 最后返回一个新的Promise() 对象
    //  状态 改变: fun1(), fun2(), fun3() 三个实例对象 谁的状态先改变(不管成功还是失败),则p的状态都会随之跟随改变   如果fun1(), fun2(), fun3() 三个实例对象 先改变的状态是成功,则成功,如果失败则失败
    //  
    const p = Promise.race([fun1(), fun2(), fun3()]);
    console.log(p);
    p.then(res => {
    
    
        console.log(res);            
    }).catch(err => {
    
    
        console.log(err);
    })
</script>

在这里插入图片描述 我们看下先改变的值为成功的情况

function fun1() {
    
    
        return new Promise((resolve, reject) => {
    
    
            setTimeout(() => {
    
    
                console.log('setTimeout1');
              resolve('setTimeout1 的 data1  成功');
            }, 1000)
        })
    }

在这里插入图片描述

async 函数

async 函数 是一个异步操作, 返回的是一个Promise()对象
await 等待 ; 在 async函数中使用 通常情况下 await 后是一个Promise()对象, 如果不是,会自动转换为Promise()对象

 <script>
    //async 函数 是一个异步操作, 返回的是一个Promise()对象 
 // await 等待 ; 在 async函数中使用   通常情况下 await 后是一个Promise()对象, 如果不是,会自动转换为Promise()对象
  async function fun(val) {
    
    
       // console.log(1);
        let res=await fun2();//  await 等待的结果 最终就是一个具体的值, 
        return 'hello  ' + res;
    }
    async function fun2() {
    
    
      //  console.log(2);
        return 'world';
    }
    fun().then(function(res){
    
    
        console.log(res);//hello  world
    }) 
</script> 
 <script>
    async function fun() {
    
    
        let res3 = await new Promise((resolve) => {
    
    
            resolve('这是Promise对象');
        })
        return 'hello   ' + res3;//async和await基础.html:39 hello   这是Promise对象
    }
    fun().then(function (res) {
    
    
        console.log(res);
    })
</script> 

当Promise()方法 有多个then()时用 async方法

    <script>

        //  基础函数
        function longTime(time) {
    
    
            return new Promise((resolve, reject) => {
    
    
                setTimeout(() => {
    
    
                    resolve(time + 500)
                }, time)
            })
        }
       
        //  三个函数 time1() ==> time2() ===> time3()  通过Promise() 实现
        //  1的输出值2要用,2的输出值3要用,然后输出3的值
     
        function time1(n){
    
    
            return longTime(n);//这是一个方法
        }

      /*  time1(500).then(res1 => {
            console.log(res1);//1000
            time1(res1).then(res2 => {
                console.log(res2);//1500
                time1(res2).then(res3 => {
                    console.log(res3);//  2000                  
                })                
            })            
        })

/*    也可以直接用基础函数
        longTime(500).then(res1 => {
            return longTime(res1);
        }).then(res2 => {
            console.log(res2);  1500
            return longTime(res2) ;           
        }).then(res3 => {
            console.log(res3); //2000           
        })*/
    
/* ====上述方法的简写
        time1(500).then(res1 => {
            return time1(res1);
        }).then(res2 => {
           // console.log(res2);  1500
            return time1(res2) ;           
        }).then(res3 => {
            console.log(res3); //2000           
        })
*/
  //  使用 async 函数实现

/*
        async function test(n){
           let res = await longTime(n)
        //    console.log(res);    
            return res;   
        }
        test(500).then(res1 => {
          //  console.log(res1); 
           return longTime(res1)      
        }).then(res2 => {
           // console.log(res2);  
            return longTime(res2)             
        }).then(res3 =>{
            console.log(res3);    //2000        
        })*/


        //  如果存在三个函数这样写
          async function time1(n){
    
     
               return  await longTime(n)
            }
            async function time2(n){
    
    
                return  await longTime(n)
            }
            async function time3(n){
    
       
                return  await longTime(n)
            }
            async function test(n){
    
    
                let res1 = await time1(n);
                let res2 = await time2(res1);
                let res3 = await time3(res2);
                console.log(res3); //2000           
            }
            test(500);

    </script>

宏任务和微任务

来源
js 是单线程执行的,js中的任务按顺序一个一个的执行,但是一个任务耗时太长;
那么后面的任务就需要等待,为了解决这种情况,
将任务分为了同步任务和异步任务;

而异步任务又可以分为微任务和宏任务。

宏任务和微任务的分类

宏任务:

setTimeout(定时器每隔多久后执行一次这个函数)

setInterval(定时器只在指定时间后执行一次这个函数)

js主代码

setImmediate(Node)

requestAnimationFrame(浏览器)
微任务:

process.nextTick(node.js中的内容)

Promise的then方法

在没有async(等待)执行过程是

  • 执行所有同步的,然后执行异步的

  • 存在微任务的话,那么就执行所有的微任务

  • 微任务都执行完之后,执行下一个宏任务

小知识:定时器(宏任务)是最后执行
具体解释在 es6收藏

猜你喜欢

转载自blog.csdn.net/z18237613052/article/details/114829686