同步,异步及Promise的详解

Promise : ES6 出来处理异步问题的内置类,用于解决异步的回调地狱问题 ;
要想彻底的整明白promise,首先我们从什么是同步什么是异步开始讲起。

一、同步和异步

    同步:
    1.从上往下按顺序依次执行
    2.只有将一个任务完全执行完后, 才执行后面的
    3.会阻塞后面的代码执行
    异步:
    1.启动任务后, 立即向下继续执行, 等同步代码执行完后才执行回调函数
    2.不会阻塞后面的代码执行
    3.异步回调函数会即使触发了, 也是要先放入队列中待执行, 只有当同步任务或前面的异步任务执 行完才执行        
        //同步执行
        console.log(111);
        function fn(cb) {
            setTimeout(() => {
                console.log(333);
                cb();
            });
        }
        console.log(222)
//异步执行
 fn(function(){
            console.log("异步之后执行的代码");
        })

二、回调函数是ES5里处理异步顺序的解决方案

回调函数会出现一些问题,回调函数容易写成回调地狱
回调地狱 :回调函数出现层层嵌套;(可维护性差,可读性差,代码不够优雅)

function fn(cb) {
            setTimeout(() => {
                cb();
            }, 1000);
        }

        fn(function () {  // 回调地狱 ;
            // 标志异步fn函数执行完毕
            console.log(111);
            fn(function () {

                console.log(222);
                fn(function () {

                    console.log(3333);
                    fn(function () {
                        console.log(4444);
                    })
                })
            })
        })

三、回调地狱解决的三种方式?

 1.ES6里的 promise  
 2.async await 解决回调地狱;  
 3.观察者模式
1.Promise
1.promise的三种状态:
   1.pending 没有任何操作
   2.resolved/fulfilled 成功的状态
   3.rejected 失败的状态

1.没有任何操作 pending :promise对象状态是 pending,值是undefined ;

        let p = new Promise(function(resolve,reject){
        });
        console.log(p);
        // [[PromiseState]]:pending  ;  [[PromiseResult]]:undefined

如图所示:
没有任何操作 pending 2.调取 resolve参数 ;fufilled

 /* 
    [[PromiseState]]:fufilled (成功)
    [[PromiseResult]]:是 resolve函数里传的参数;
  */
 let p = new Promise((resolve,reject)=>{
            resolve(456)
        })
        console.log(p);
        var obj = {
            myname:"张三"
        }
        console.log(obj);
        setTimeout(() => {
            obj.myname = "李四";
        },10);

如图所示:
调取 resolve参数 ;fufilled 3.失败的状态 rejected

        /* 
             [[PromiseState]]:rejected (失败)
             [[PromiseResult]]:是 reject里传的值;
        */
        let p = new Promise((res,rej)=>{
            rej("err");
        })
        console.log(p);

如图所示:
失败的状态  rejected

2.Promise对象的then方法
每一个promise对象都会有一个then方法
then方法里有2个回调函数,onResolved和onRejected。

1.onResolved: 在调取 resolve函数的时候执行  (then里的第一个回调函数)
            promiseState : fufilled 状态的时候
            promiseResult: 作为 onResolved函数的参数; 
 2.onRejected : 在调取reject 函数的时候执行;(then里的第二个回调 函数);
             promiseState : rejected 状态的时候
             promiseResult: 作为 onRejected函数的参数;

1.onResolved回调函数 参数 是promiseResult的结果值;

代码如下:

  /* 
    调用 resolve 的时候  promiseState 变成 fufilled状态  
    promiseResult 是传递的参数 success  
   */
    let p = new Promise((resolve,reject)=>{
            setTimeout(() => {
                resolve("success");
                // reject("错误");
            }, 2000);
        })
     console.log(p);
        p.then(function(res){   // 是成功状态的promise对象的promiseResult结果值;
            console.log("onResolved执行了",res);
        },function(){
            console.log("onRejected执行了");
        });    

结果展示如下:
在这里插入图片描述
2.onRejected回调函数
代码如下:

   let p = new Promise((resolve,reject)=>{
            setTimeout(() => {
                // resolve("success");
                reject("错误");
            }, 2000);
        })
    console.log(p);
    p.then(function(res){   // onResolved  函数
            console.log("onResolved",res)
        },function(err){  // onRejected函数
            console.log("onRejected",err);
        })     

结果展示如下:
onRejected回调函数

3.promise简单使用

1.通过回调函数解决异步执行顺序问题

        function fn(cb){
            setTimeout(() => {
                console.log("fn函数执行了");
                cb();
            }, 2000);
        }


        fn(function(){
            console.log("异步函数执行之后在执行的代码");
        });

2.通过promise 来解决异步函数的执行顺序问题;

        function fn() {
            let p = new Promise(resolve => {
                setTimeout(() => {
                    console.log("fn函数执行了");
                    resolve("success");  
                    // 函数执行完毕之后执行resolve方法
                }, 2000);
            })
            return p;  // 返还promise对象;
        }
        fn().then(function(res){
            console.log("异步函数执行之后在执行的代码",res);
        },function(err){
            console.log(err);
        })
4.then的返还值

既然已经会简单使用promise,那我们进一步了解then的返还值。
它一共有四种情况,代码如下:

  1. 如果then 的 onResolved 和 onRejected里没有任何返还;
     // then会返还一个 
     //promiseState: fufilled     promiseResult:undefined
     // 无论调取的是 resolve 还是reject 都是一个成功状态promise对象;
     let p = new Promise((resolve, reject) => {
            resolve("success");
            reject("err");
        })
       let p2 = p.then(function (res) {
            console.log(res)
        }, function (err) {
            console.log(err);
        });
        console.log(p2);  

2.如果then的onResolved和onRejected 里有普通的返还值

 // then的返还值 是一个fufilled状态的promise对象,promiseResult就是返还的内容
 // 无论是调取的resolve 还是reject 都会是一个fufilled状态promise对象 promiseResult就是返还的内容;
        let p2 = p.then(function (res) {
            console.log(res)
            return 1111; 
        }, function (err) {
            console.log(err);
            return 2222;
        });
        console.log(p2);

打印如下:
在这里插入图片描述3.在then的 onResolved 及onRejected 里返还一个promise对象
会把 onResolved 及onRejected 里返还的promise对象原封不动返还出来

(1)then的 onResolved

        let p = new Promise((resolve, reject) => {
            resolve("success"); //如果是onResolved
            // reject("err");
        })
         let p2 = p.then(function (res) {
            console.log(res)
            return new Promise(resolve=>{
                resolve(1111);
            });
        }, function (err) {
            console.log(err);
            return new Promise(resolve=>{
                resolve(222);
            });
        });
        console.log(p2);

在这里插入图片描述
(2)在then的 onRejected

       let p = new Promise((resolve, reject) => {
            // resolve("success");
            reject("err"); //如果是onRejected
        })
       let p2 = p.then(function (res) {
            console.log(res)
            return new Promise(resolve=>{
                resolve(1111);
            });
        }, function (err) {
            console.log(err);
            return new Promise(resolve=>{
                resolve(222);
            });
        });
        console.log(p2);

在这里插入图片描述4.在then的onResolved 及onRejected 抛出了错误,那么then的返还值就得到一个 rejected状态的promise对象

   let p = new Promise((resolve, reject) => {
            // resolve("success");
            reject("err");
        })
   let p2 = p.then(function (res) {
            console.log(res)
            throw new Error("错了");         
        }, function (err) {
            console.log(err);
            throw new Error("错了222");         
        });
   console.log(p2);

打印结果如图:
在这里插入图片描述以上就是then的四种返还值情况。

5. then的链式调用
 上一章我们了解了then的返还值:
 1.回调没返还 promise对象 
 2.返还普通值 promise对象 
 3.返还promise对象 ,原封不动的返还promise对象 
 4.抛出错误 返还一个失败状态的promise对象;
 
 由此可以得出:
 无论如何 then的返还值 都是一个promise对象,每个promise对象都会有then方法;

我们可以进一步掌握then的链式调用,如下:
1.无限链式调用

        let p = new Promise(res=>{
            res(11);
        })
        let p2 =   p.then(res=>{  // p2 是promise对象
            console.log(res);
            // return 222
            return new Promise(res=>{
                res(333);
            })
        },err=>{
            console.log(err)
        })
        p2.then(res=>{
            console.log(res)
        },err=>{
        }) 

2.链式的使用 ;依次让异步执行;

 // 链式的使用 ;依次让异步执行;

        function fn1() {
            return new Promise(reslove => {
                setTimeout(() => {
                    console.log(111);
                    reslove();
                }, 1000);
            })
        }


        function fn2() {
            return new Promise(resolve => {
                setTimeout(() => {
                    console.log(222)
                    // cb();
                    resolve();
                }, 1000);
            })

        }

        function fn3() {
            return new Promise(resolve => {
                setTimeout(() => {
                    console.log(333)
                    resolve();
                }, 1000);
                
            })

        }
        // then的链式调用
        fn1().then(() => {
            console.log("第一个执行完毕");
            // fn2().then(()=>{
            // })
            return fn2();
        }).then(() => {
            console.log("第二个执行完毕");
            return fn3();
        }).then(()=>{
            console.log("第三个执行完毕");
        })

6.then的穿透

在then里的回调函数,无论是 onResolved 还是 onRejected 回调函数,只要传入的参数 不是函数,那么 then就会出现穿透现象。会把之前的promise对象原封不动的返还回来;

       let p = new Promise((resolve,reject)=>{
            // resolve("1111");
            reject(222);
        })

        p.then(res=>{  // 正常写法
        },err=>{
            console.log(err);
        })
7.then是异步的

根据刚开始我们讲到同步是依次执行,异步是同步代码执行完后才执行回调函数。
我们用代码来证明then是同步还是异步。

         console.log(111);
         setTimeout(() => {
            console.log(222)
         });
         let p = new Promise(reslove=>{
            console.log(333);
            reslove();
         })
         p.then(()=>{
            console.log(444)
         })
         console.log(555)

输出结果为111-333-555- 444-222

我们可以看出444和222都为异步,为什么4在2的前面呢?

8.微任务和宏任务

接下来讲到异步中的微任务和宏任务。

 微任务:可以插队,promise里的then就是微任务 ,颗粒度更小 (精度更高)
 提高任务的响应精度;
        微任务队列 : 【1】【2】【3】【4】【5】【6】
                                |                【7(需要立刻响应的任务)】

  宏任务 :有定时器 ,网络请求,资源加载(其他基本都是宏任务) (颗粒度大,精度差)
  宏任务一定需要排序执行不能插队,精度随机
                [1][2][3][4][5][6]
                                    [7]

执行顺序 :会先执行宏任务 ,在执行宏任务后的微任务队列
(表现上是微任务先执行;)

9.promise的实例方法
1.catch:
1.捕捉错误 是 onRejected的别名 ,异步微任务,返还值和onRejected一样。   
2.捕获then链式上的错误 。 后期写then的时候写一个回调后面在加上一个catch就可以了;
        // promise的实例方法
        let p = new Promise((resolve, reject) => {
            // resolve(111);
            reject("error");
        })
        
        // catch返还值 和 onRejected 回调返还值一样;
        // catch 也是异步的 ,也是微任务;
            console.log(111);
           let p2 =  p.then(res=>{
                console.log(res);
            }).catch(err=>{
                console.log(err);
                return 111;
            })
            console.log(p2);
            console.log(222);

在这里插入图片描述catch 可以捕捉 then链式上的错误;

        let p = new Promise((resolve, reject) => {
            resolve(111);
            reject("error");
        })
        function fn1() {
            let p1 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(111);
                }, 1000);
            })
            return p1;
        }


        function fn2() {
            let p2 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(222);
                    // reject("第二个错误了");
                }, 1000);
            })
            return p2;
        }
        function fn3() {
            let p3 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    // resolve(333);
                    reject("第三个错误了");
                }, 1000);
            })
            return p3;
        }

        fn1().then(res=>{
            console.log(res);
            return fn2();
        }).then(res=>{
            console.log(res);
            return fn3();
        }).then(res=>{
            console.log(res);
        }).catch(err=>{
            console.log("catch",err);
        })
2.finally :最后
promise执行完毕(成功、失败)之后 调用finally里的回调函数;
finally 里的回调函数没有参数;
        let p = new Promise((resolve,reject)=>{
            setTimeout(()=>{
                // resolve("success");
                reject("err");
            },2000)
        })

        p.then(res=>{
            console.log(res);
        }).finally(()=>{
            console.log("会在promise执行完毕之后调用");
        })
3.all
Promise.all([p1, p2, p3])
接收包含多个promise的数组, 返回一个新的promise
只有当所有接收的promise都成功了, 返回的promise才成功, 且成功的value为所有成功promise的value组成的数组
一旦有一个失败了, 返回的promise就失败了, 且失败的reason就是失败promise的reason
4.race
 Promise.race([p1, p2, p3])
 接收包含多个promise的数组, 返回一个新的promise
 返回的promise的结果由第一个完成的promise决定
2.async 和 await

ES8: async 和 await 是 异步的终极解决方案,是 then的语法糖;
作用: 简化promise对象的使用, 不用再使用then/catch来指定回调函数
注意:
调用async函数得到是一个promise, 其结果状态由async函数体执行的结果决定
await的右侧也可以不是promise, 如果不是, 直接返回表达式的值
一、基本使用
改写了then的链式调用;用同步的写法实现异步调用;

        function fn1() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(111)
                }, 1000);
            })
        }


        function fn2() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(222)
                    // reject("22错误了");
                }, 1000);
            })
        }


        function fn3() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(333)
                }, 1000);
            })
        }

        // 让三个异步函数依次执行 ;
        // fn1().then(res=>{  错误的依次执行;
        //     console.log(res);
        // })
        // fn2().then(res=>{
        //     console.log(res);
        // })
        // fn3().then(res=>{
        //     console.log(res);
        // })

        // async await 改写了 then的调用方式;
        // fn1().then(res=>{
        //     console.log(res);
        //     return fn2();
        // }).then(res=>{
        //     console.log(res);
        //     return fn3();
        // }).then(res=>{
        //     console.log(res);
        // }).catch(err=>{
        //     console.log(err);
        // })

        async function fn() {
            let res = await fn1();
            console.log(res);
            let res2 = await fn2();
            console.log(res2);
            let res3 = await fn3();
            console.log(res3);
        }

        fn(); // 调用函数;
1.async 及 await 涉及的问题

1.捕捉错误使用try… catch…
注意 catch的写法 和then里catch的写法不同 ;

 try {
       let res = await fn1();
         console.log(res);
       let res2 = await fn2();
         console.log(res2);
        let res3 = await fn3();
         console.log(res3);
       }catch{
         console.log("错了");
      }

2.async 和 await 不能出现在嵌套函数里;
3.await 只会等待一个async函数里的异步;

3.观察者模式

未完待续。。。。。

以上就是关于同步,异步及promise的具体使用方法。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Promise和async/await都是用于处理JavaScript中的异步操作的工具。它们可以帮助我们更简洁地编写异步代码,并使其更易于阅读和维护。 Promise是一种表示异步操作的对象。它可以有三种状态:Pending(进行中)、Fulfilled(已完成)和Rejected(已拒绝)。当一个Promise对象的状态改变时,它会调用相应的回调函数。 我们可以使用Promise来处理异步操作。通过调用Promise的构造函数并传入一个执行器函数,我们可以创建一个新的Promise对象。执行器函数接受两个参数:resolve和reject。当异步操作成功时,我们可以调用resolve函数将Promise的状态设置为Fulfilled,并传递一个值作为结果。当异步操作失败时,我们可以调用reject函数将Promise的状态设置为Rejected,并传递一个错误对象。 我们可以使用Promise的then方法来处理已完成状态的Promise。then方法接受两个回调函数作为参数:第一个回调函数在Promise成功时被调用,第二个回调函数在Promise失败时被调用。 同时,我们可以使用Promise的catch方法来处理已拒绝状态的Promise。catch方法接受一个回调函数作为参数,该回调函数在Promise被拒绝时被调用。 async/await是基于Promise的语法糖,使异步代码更像同步代码。async函数是一个返回Promise对象的函数,其中使用了await关键字来暂停函数的执行,直到Promise解决(Fulfilled)或拒绝(Rejected)。 在使用async/await时,我们可以使用try/catch语句来捕获Promise中的错误。在try块中,我们可以使用await关键字来等待一个Promise的解决或拒绝。如果Promise被解决,则await表达式将返回解决的值;如果Promise被拒绝,则抛出一个错误对象,可以使用catch块捕获该错误。 总结一下,Promise是一种用于处理异步操作的对象,它有三种状态:进行中、已完成和已拒绝。我们可以使用Promise的then和catch方法来处理已完成和已拒绝状态的Promise。而async/await是基于Promise的语法糖,使异步代码更像同步代码。通过使用async函数和await关键字,我们可以以更简洁的方式编写异步代码,并使用try/catch语句来处理错误。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值