• Promise异步async&await



    在这里插入图片描述
    JavaScript是单线程的,在代码的执行过程中,碰见异步代码,先单独放置另一队列,原有队列继续执行(不被阻塞)。

    引入

    如果我们需要依次的执行多个异步操作,我们的代码可能就要写成这样,这个我们就叫作 回调地狱(Callback Hell)。
    Promise就是为了解决这个问题。

    // 异步操作进行层层嵌套,使得依次执行
            setTimeout(() => {
                console.log("异步1要做的事情");
                setTimeout(() => {
                    console.log("异步2要做的事情");
                    setTimeout(() => {
                        console.log("异步3要做的事情");
                    },2000)
                },1000)
            },3000)
            console.log("虽然我在后面,但是我不会等前面的异步操作");
            console.log("666");
            console.log("你说呢");
    // 程序会依次执行 异步1 -> 异步2 -> 异步3
    // 3s -> 1s -> 2s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    执行结果:
    在这里插入图片描述

    Promise

    为什么出现 Promise
    遇到一个请求要依赖前一个请求的结果,如果多个层层回调函数的嵌套叫做“回调地域”,代码不美观而且不易于维护。
    Promise的优点在于可以用链式结构将多个异步操作串联起来
    Promise 对象有三个状态:pending、fulfilled 和 rejected。
    resolve :在异步操作成功时调用,将异步操作的结果,作为参数传递出去,并使Promise状态变为fulfilled。
    reject :在异步操作失败时调用,将异步操作报的错误,作为参数传递出去,并使Promise状态变为 rejected。

    // 链式调用, 顺序执行异步
            axios.get(url)
            .then()
            .then()
            .catch()
            .finally();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
            const promise = new Promise((resolve,reject) => {
                // 这里做异步任务 axios 等 暂且用 setTimeout 模拟
                //------------- 
                setTimeout(function(){
                    let data = {retCode:0,msg:'jkl'};
                    if(data.retCode == 0){
                        // 异步操作成功
                        resolve(data);									// pending -> fullfilled
                        console.log("成功执行");
                    }else{
                        // 异步操作失败
                        reject({retCode:-1,msg:'netWork error'});		// pending -> rejected
                        console.log("执行失败");
                    }
                },1000);
                //-------------
                console.log("fewfewgwegweg");
            });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述
    这个Promise对象是会立即执行的。
    then方法和catch方法都是异步代码
    当Promise对象中是resolve时,外面可以没有then去处理。
    当Promise对象中是reject时,外面要么then要写第二个函数参数去处理,要么使用链式catch的方式去处理,反正必须要处理。

    async&await

    async关键字,是声明异步函数,返回值是promise对象,如果返回的不是promise,会自动用Promise.resolve()包装。
    await 后 是一个 Promise对象。

            const fun1 = function(){
                return new Promise((resolve,reject) => {
                    // 异步操作 1
                    resolve("data1....")
                });
            };
            const fun2 = function(){
                return new Promise((resolve,reject) => {
                    // 异步操作 2
                    resolve("data2....")
                });
            };
    
            const asyncFun = async function(){
                let res1 = await fun1();
                let res2 = await fun2();
                
                console.log("hello"); 
                console.log(res1);				// data1....
                console.log(res2);				// data2....
            }
            asyncFun();
            console.log("sffsdgd");  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述
    await等后面的promise对象执行完毕,然后拿到resolve()的值并进行返回,之后继续向下执行。
    如果 Promise中没有 resolve,就会引起 asyncFun 函数内部执行的阻塞,await一直在等待,只打印 sffsdgd
    但是对于 asyncFun 函数 外部的代码来说没有影响。

    Attention:
    await 命令后面的 Promise 对象,运行结果可能是 rejected,所以最好把 await 命令放在 try…catch 代码块中。

    async function myFunction() {
      try {
        await somethingThatReturnsAPromise();
      } catch (err) {
        console.log(err);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    JS异步顺序调用
    await用法
    Promise
    Promise详解

    Promise处理多次 Ajax 请求

            function queryData(url) {
                return new Promise((resolve, reject) => {
                    let xhr = new XMLHttpRequest();
                    xhr.onreadystatechange = function() {
                        if (xhr.readyState != 4) return;
                        if (xhr.readyState == 4 && xhr.status == 200) {
                            // 处理正常情况
                            // xhr.responseText 是从接口拿到的数据
                            resolve(xhr.responseText); 
                        } else {
                            // 处理异常情况
                            reject('接口请求失败');
                        }
                    };
                    xhr.responseType = 'json'; // 设置返回的数据类型
                    xhr.open('get', url);
                    xhr.send(null); // 请求接口
                });
            }
            // 发送多个ajax请求并且保证顺序
            queryData('http://localhost:3000/api1')
                .then(
                    data1 => {
                        console.log(JSON.stringify(data1));
                        // 请求完接口1后,继续请求接口2
                        return queryData('http://localhost:3000/api2');
                    }
                )
                .then(
                    data2 => {
                        console.log(JSON.stringify(data2));
                        // 请求完接口2后,继续请求接口3
                        return queryData('http://localhost:3000/api3');
                    }
                )
                .then(
                    data3 => {
                        // 获取接口3返回的数据
                        console.log(JSON.stringify(data3));
                    }
                );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    then方法
    return 后面的返回值,有两种情况:
    情况1:返回 Promise 实例对象。返回的该实例对象会调用下一个 then。
    情况2:返回普通值。返回的普通值会直接传递给下一个then,通过 then 参数中函数的参数接收该值。

           .then(data2 => {
                console.log(JSON.stringify(data2));
                // 返回普通值
                return 'qianguyihao';
            })
            /*
                这里会产生一个新的 默认的 promise实例,来调用这里的then,确保可以继续进行链式操作。
            */
            .then(data3 => {
                // 这里的 data3 接收的是 普通值 'qianguyihao'
                console.log(data3);
            });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    PHP中=>和->有什么区别?
    【C++】结构体、类和引用
    数智化重塑冷链物流行业,SaaS云系统开发方案赋能冷链企业实现高效运营
    Redis(1)- Redis数据库的安装和配置
    redis 介绍
    2022.11.14-11.20 AI行业周刊(第124期):给自己的礼物
    盛最多水的容器
    [附源码]Python计算机毕业设计Django咖啡销售平台
    续---初识HTML!!!(结束篇)
    紫禁之巅-Unity游戏开发教程:勇者斗恶龙之魔法石
  • 原文地址:https://blog.csdn.net/qq_53318060/article/details/124595412