zoukankan      html  css  js  c++  java
  • Promise和Async/Await用法整理

    1.Promise

    1.简介

    Promise,简单来说就是一个容器,里面保存着某个未来才会结束的时间(通常是一个异步操作的结果)

    Promise对象的基本语法:

    new Promise((resolve,reject) => {
    	//.....
    });
    

    从语法上来说,Promise是一个对象,从它可以获取异步操作的消息。

    基本语法:

    let p = new Promise((resolve,reject) => {
        //...
        resolve('success')
    });
    
    p.then(result => {
        console.log(result);//success
    });
    

    Promise对象特点和三个状态:
    这里写图片描述

    例如:

    let p = new Promise((resolve,reject) => {
        //...
        resolve('success');
        console.log('after resolve');
        reject('error');
    });
    
    p.then(result => {
        console.log(result);
    });
    
    p.catch(result => {
        console.log(result);
    })
    

    运行结果:
    after resolve
    success

    resolve下面的语句其实是可以执行的,那么为什么reject的状态信息在下面没有接受到呢?这就是因为Promise对象的特点:状态的凝固。new出一个Promise对象时,这个对象的起始状态就是Pending状态,在根据resolve或reject返回Fulfilled状态/Rejected状态。

    2.

    这里写图片描述

    Then分别接受resolve和reject的信息,有三种参数形式,第三种比较“怪异”,只用来接收做reject处理。

    eg:

    let p = new Promise((resolve,reject) => {
        //...
        let random = Math.random();//小于1大于0
        if(random > 0.4) {
            resolve('random > 0.4');
        }else {
            reject('random <= 0.4');
        }
    });
    
    p.then(result => {
        console.log('resolve',result);
    }, result => {
        console.log('reject',result);
    });
    
    
    

    3.链式调用

    我们来执行一段代码:

    let p = new Promise((resolve,reject) => {
        reject('reject');
    });
    
    let resultP = p.then(null,result => {
        console.log(result);
    });
    
    console.log(resultP);
    

    结果:
    Promise { }
    reject

    js的执行顺序就是这样,同步->异步->回调,在同步执行的时候,Promise对象还处于pending的状态,也说明了这个then返回的是一个Promise对象。

    而且必须在then里面给一个返回值,才能继续调用,否则undefined。
    eg:

    let p = new Promise((resolve,reject) => {
        reject('error');
    });
    
    let resultP = p.then(null,result => {
        console.log(result);
        return 123;
    });
    
    // console.log(resultP);
    resultP.then(tmp => {
        console.log(tmp);
    })
    

    结果:
    error
    123

    4.catch

    这里写图片描述

    eg:

    let p = new Promise((resolve,reject) => {
        reject('error');
    });
    
    p.catch(result => {
        console.log(result);
    })
    

    那这个catch的返回值是什么呢:
    和上面then是一样的。

    5.Promise.resolve()

    这里写图片描述

    传一个普通的对象:

    // let p1 =Promise.resolve(123);
    let p1 =Promise.resolve({name:'xixi',age:'xxxx'});
    
    p1.then(result => {
        console.log(result);
    });
    

    如果是Promise对象呢,直接返回

    let p = new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve('success');
        },500);
    });
    
    let pp = Promise.resolve(p);
    
    pp.then(result => {
        console.log(result);
    });
    
    console.log(pp == p);
    

    结果:
    true
    success

    6.Promise.reject()

    这里写图片描述

    eg:

    let p = Promise.reject(123);
    
    console.log(p);
    
    p.then(result => {
        console.log(result);
    }).catch(result => {
        console.log('catch',result);
    })
    

    结果:
    Promise { 123 }
    catch 123

    7.Promise.all()

    这里写图片描述

    eg:

    let p1 = Promise.resolve(123);
    let p2 = Promise.resolve('hello');
    let p3 = Promise.resolve('success');
    
    
    Promise.all([p1,p2,p3]).then(result => {
        console.log(result);
    })
    

    结果:
    [ 123, 'hello', 'success' ]

    成功之后就是数组类型,当所有状态都是成功状态才返回数组,只要其中有一个的对象是reject的,就返回reject的状态值。
    eg:

    let p1 = Promise.resolve(123);
    let p2 = Promise.resolve('hello');
    let p3 = Promise.resolve('success');
    let p4 = Promise.reject('error');
    
    // Promise.all([p1,p2,p3]).then(result => {
    //     console.log(result);
    // });
    
    Promise.all([p1,p2,p4]).then(result => {
        console.log(result);
    }).catch(result => {
        console.log(result);
    });
    

    结果:
    error

    又一个eg:

    //用sleep来模仿浏览器的AJAX请求
    function sleep(wait) {
        return new Promise((res,rej) => {
            setTimeout(() => {
                res(wait);
            },wait);
        });
    }
    
    let p1 = sleep(500);
    let p2 = sleep(500);
    let p3 = sleep(1000);
    
    Promise.all([p1,p2,p3]).then(result => {
        console.log(result);
        //.....
        //loading
    });
    

    8.Promise.race

    这里写图片描述

    和all同样接受多个对象,不同的是,race()接受的对象中,哪个对象返回的快就返回哪个对象,就如race直译的赛跑这样。如果对象其中有reject状态的,必须catch捕捉到,如果返回的够快,就返回这个状态。race最终返回的只有一个值。
    eg:

    //用sleep来模仿浏览器的AJAX请求
    function sleep(wait) {
        return new Promise((res,rej) => {
            setTimeout(() => {
                res(wait);
            },wait);
        });
    }
    
    let p1 = sleep(500);
    let p0 = sleep(2000);
    
    Promise.race([p1,p0]).then(result => {
        console.log(result);
    });
    
    let p2 = new Promise((resolve,reject) => {
        setTimeout(()=>{
            reject('error');
        },1000);
    });
    
    Promise.race([p0,p2]).then(result => {
        console.log(result);
    }).catch(result => {
        console.log(result);
    });
    

    500
    error

    9.异常处理

    这里写图片描述

    为什么说安静,一个例子,Pormise内部的错误外界用try-catch捕捉不到
    eg:

    try {
        let p = new Promise((resolve, reject) => {
            throw new Error("I'm error");
            // reject(new Error("I'm Error"));
        });
    }catch(e) {
        console.log('catch',e);
    }
    

    结果什么都没打印。
    但是抛出的错误可以通过catch来捕捉:

    // try {
        let p = new Promise((resolve, reject) => {
            throw new Error("I'm error");
            // reject(new Error("I'm Error"));
        });
    // }catch(e) {
    //     console.log('catch',e);
    // }
    
    
    p.catch(result => {
        console.log(result);
    });
    
    
    

    这样就捕捉到错误。所以:
    这里写图片描述

    2.Async-Await

    1.简介:

    这里写图片描述

    这里写图片描述

    async和await在干什么,async用于申明一个function是异步的,而await可以认为是async wait的简写,等待一个异步方法执行完成。

    2.基本语法

    这里写图片描述
    在Chrome里申明这样一个函数,可以在控制台看到返回的其实就是一个Promise对象。
    扩展需要了解的就是Chrome现在也支持asyncFunction,可以在Chrome控制台测试:
    console.log(async function(){}.constructor);
    ƒ AsyncFunction() { [native code] }

    3.规则

    这里写图片描述

    如图,await放在普通函数里是会报错的。

    这里写图片描述

    eg:

    async function demo() {
        let result = await Promise.resolve(123);
        console.log(result);
    }
    demo();
    

    4.应用

    Promise虽然一方面解决了callback的回调地狱,但是相对的把回调“纵向发展”了,形成了一个回调链。eg:

    function sleep(wait) {
        return new Promise((res,rej) => {
            setTimeout(() => {
                res(wait);
            },wait);
        });
    }
    
    /*
    let p1 = sleep(100);
    let p2 = sleep(200);
    let p =*/
    
    sleep(100).then(result => {
        return sleep(result + 100);
    }).then(result02 => {
        return sleep(result02 + 100);
    }).then(result03 => {
        console.log(result03);
    })
    
    

    控制台:
    300

    后面的结果都是依赖前面的结果。
    改成async/await写法就是:

    async function demo() {
        let result01 = await sleep(100);
        //上一个await执行之后才会执行下一句
        let result02 = await sleep(result01 + 100);
        let result03 = await sleep(result02 + 100);
        // console.log(result03);
        return result03;
    }
    
    demo().then(result => {
        console.log(result);
    });
    

    因为async返回的也是promise对象,所以用then接受就行了。
    结果:
    300
    需要注意的就是await是强制把异步变成了同步,这一句代码执行完,才会执行下一句。

    5.错误处理

    这里写图片描述

    如果是reject状态,可以用try-catch捕捉
    eg:

    let p = new Promise((resolve,reject) => {
        setTimeout(() => {
            reject('error');
        },1000);
    });
    
    async function demo(params) {
        try {
            let result = await p;
        }catch(e) {
            console.log(e);
        }
    }
    
    demo();
    

    结果:
    error
    这是基本的错误处理,但是当内部出现一些错误时,和上面Promise有点类似,demo()函数不会报错,还是需要catch回调捕捉。这就是内部的错误被“静默”处理了。

    let p = new Promise((resolve,reject) => {
        setTimeout(() => {
            reject('error');
        },1000);
    });
    
    async function demo(params) {
        // try {
            let result = name;
        // }catch(e) {
        //     console.log(e);
        // }
    }
    
    demo().catch((err) => {
        console.log(err);
    })
    

    6.注意你的并行执行和循环

    比如上面的例子:
    这里写图片描述

    如果这三个是你想异步发出的AJAX请求,在这段代码里其实是同步的,第一个发出去才会发第二个,所以async/await需要谨慎使用。

    这里写图片描述

    现在有一些forEach或者map的循环里,比如在forEach里使用await,这时候的上下文就变成了array,而不是async function,就会报错。这时候你就要想到是什么错误。

  • 相关阅读:
    This is very likely to create a memory leak. Stack trace of thread错误分析
    spring boot 2.0 neo4j 使用
    造个简单的轮子倒是不难,但可用性健壮性高到qt这样全世界都在用,就几乎不可能了
    0xC0000005;Access Violation(栈区空间很宝贵, linux上栈区空间默认为8M,vc6下默认栈空间大小为1M)
    Object::connect: Cannot queue arguments of type 'QMap<QString,QString>'(要使用qRegisterMetaType<StringMap>进行注册)
    QFileSystemModel只显示名称,不显示size,type,modified
    非Qt工程使用Qt的信号槽机制
    web性能权威指南(High Performance Browser Networking)
    缓存穿透 缓存并发 缓存失效
    互联网架构-基础中间件
  • 原文地址:https://www.cnblogs.com/zhangmingzhao/p/8343685.html
Copyright © 2011-2022 走看看