Promise和事件循环

发布于:2022-12-20 ⋅ 阅读:(177) ⋅ 点赞:(0)

01-Promise语法

1.1-Promise介绍

  • ES6教程传送门:http://es6.ruanyifeng.com/#docs/promise
  • 1.Promise是什么?
    • Promise 一个 构造函数, 用于创建Promise对象
      • Promise对象:可以理解为一个处理异步操作的容器
  • 2.Promise作用:解决回调地狱
    • 回调地狱:异步回调 层层嵌套
/* 
为什么要学习Promise?

1.Promise作用 : 解决回调地狱问题
    回调地狱 : 异步回调 层层嵌套
*/

//需求: 依次读取 文件  a.txt , b.txt , c.txt 这三个文件内容
const fs = require('fs');

//(1)能直接按照顺序写吗?  : 不能,因为异步操作 是无序的
fs.readFile("./data/a.txt", 'utf-8', (err, data) => {
    if(err){
        console.log(err);
    }else{
        console.log(data);
    };
});

fs.readFile("./data/b.txt", 'utf-8', (err, data) => {
    if(err){
        console.log(err);
    }else{
        console.log(data);
    };
});

fs.readFile("./data/c.txt", 'utf-8', (err, data) => {
    if(err){
        console.log(err);
    }else{
        console.log(data);
    };
});


//(2)解决方案 : 在回调函数中嵌套执行
//弊端 : 形成回调地狱(异步回调 层层嵌套,非常麻烦且不便于维护)
//读取文件A
fs.readFile("./data/a.txt", 'utf-8', (err, data) => {
    if(err){
        console.log(err);
    }else{
        console.log(data);
        //A读取成功之后开始读取B
        fs.readFile("./data/b.txt", 'utf-8', (err, data) => {
            if(err){
                console.log(err);
            }else{
                console.log(data);
                //B读取成功之后开始读取C
                fs.readFile("./data/c.txt", 'utf-8', (err, data) => {
                    if(err){
                        console.log(err);
                    }else{
                        console.log(data);
                    }
                });
            }
        });
    }
});

1.2-Promise基本使用

  • 1.实例化Promise对象
    • 作用: 将异步操作代码 放入 Promise中
      • resolve:异步操作 成功状态
      • reject : 异步操作 失败状态
    • new Promise((resolve,reject)=>{ 你的异步操作 })
  • 2.调用then()方法处理异步操作结果
    • promise对象.then((data)=>{ 处理成功数据 },(err)=>{ 处理失败信息 });
/* 
1.Promise是一个构造函数 , 返回一个Promise对象
2.使用流程
    (1)实例化Promise对象 : 将异步操作放入Promise中
    (2)调用then() 方法: 处理异步操作结果
*/

const fs = require('fs');
/** 1. 实例化Promise
* @description:实例化Promise
* @param {Function}  (resolve:成功处理函数,reject:失败处理函数)=>{ 异步操作代码 }
* @return: Promise对象
*/
 const p1 = new Promise((resolve,reject)=>{
     //读文件
     fs.readFile('./data/a.txt','utf8',(err,data)=>{
        if(err == null){ 
            /* 
            (1)异步操作成功,则执行 resolvce()
            (2)resolve会把把promise对象的状态从 pending进行中 改为 fulfilled成功
            (3)该方法本质是调用 then() 中的第一个方法
            */
            resolve(data);
        }else {
            /* 
            (1)异步操作失败,则执行 reject()
            (2)reject会把把promise对象的状态从 pending进行中 改为 rejected失败
            (3)该方法本质是调用 then() 中的第二个方法
            */
            reject(err); 
        }
     });
 });

 /* 2. p1.then() : 处理异步操作结果 */
 p1.then((data)=>{
    //成功了,打印文件数据
    console.log(data);
 },(err)=>{
    //失败了,打印错误信息
    console.log(err);
 });

1.3-Promise特点介绍(原理篇)

promise本身并没有改变异步的顺序,而是通过操作异步结果的顺序从而'间接'控制异步的顺序

promise本质 不是控制 异步代码的执行顺序(无法控制) , 而是控制异步代码结果处理的顺序

**promise本身只是一个容器,真正异步的是它的两个回调resolve()和reject() **

/**
 * 1.promise对象有三个状态.
    a. pending(进行中)
    b. fulfilled(已成功)
    c. rejected(已失败)
 
 * 2.Promise对象的状态改变, 只有两种可能:
    a. 从pending变为fulfilled
        * 此时应该执行 resolve();
    b. 从pending变为rejected。
        * 此时应该执行 reject();
 
 * 3.promise在创建对象的时候,里面的代码会立即执行.
    a. promise创建时,里面的代码还是异步无序操作
    b. promise的原理是,利用then方法将异步操作的结果 按照顺序执行
    *** 总结: 不要在创建promise的时候去处理异步操作结果,而应该通过 then() 方法来处理 ***

 * 4.promise解决回调地狱原理 : 在then方法中返回一个promise对象
    *** 在上一个promise的then方法中,返回下一个promise ***

 * 5.坤哥结语 : promise本质 不是控制异步代码的执行顺序(无法控制) , 而是控制异步代码结果处理的顺序
*/

const fs = require('fs');

//(1) 创建三个异步操作  promise

//读取文件A
const p1 = new Promise((resolve,reject)=>{
    //读文件
    fs.readFile('./data/a.txt','utf8',(err,data)=>{
       if(err == null){ 
            //成功
           resolve(data);
       }else {
           //失败
           reject(err); 
       }
    });
});

//读取文件B
const p2 = new Promise((resolve,reject)=>{
    //读文件
    fs.readFile('./data/b.txt','utf8',(err,data)=>{
       if(err == null){ 
            //成功
           resolve(data);
       }else {
           //失败
           reject(err); 
       }
    });
});

//读取文件C
const p3 = new Promise((resolve,reject)=>{
    //读文件
    fs.readFile('./data/c.txt','utf8',(err,data)=>{
       if(err == null){ 
            //成功
           resolve(data);
       }else {
           //失败
           reject(err); 
       }
    });
});

// (2)按照顺序处理异步操作结果
p1.then((data)=>{//第一个异步结果
    console.log(data);
    return p2;//返回下一个promise
}).then((data)=>{ // 第二个异步结果  (由于p1.then方法返回的是p2,而p2也有自己的then,所以可以继续调用p2的then方法)
    console.log(data);
    return p3;//返回下一个promise
}).then((data)=>{ // 第三个异步结果  
    console.log(data);
});


1.4-Promise解决回调地狱封装

const fs = require('fs');


//1.封装一个函数 :  根据文件名生成  文件读取的promise
function getPromise(fileName) {
    let p = new Promise((resolve, reject) => {
        //读文件
        fs.readFile(`./data/${fileName}.txt`,'utf-8', (err, data) => {
            if (err == null) {
                //成功
                resolve(data);
            } else {
                //失败
                reject(err);
            }
        });
    });
    return p;
};

//2.解决需求: 要先读a, 读完a后读b, 读完b后读c.

//开始读取a
getPromise('a').then((data)=>{
    console.log(data);
    //继续读取b
    return getPromise('b');
}).then((data)=>{
    console.log(data);
    //继续读取c
    return getPromise('c');
}).then((data)=>{
    console.log(data);
});//异步回调队列结束

1.5-Promise对象的catch方法

  • catch:用于捕获异步操作的错误信息
const fs = require("fs");

/* 
promise实例对象的catch方法 : 用于捕获异步操作的错误信息
*/


//1.封装一个函数 :  根据文件名生成  文件读取的promise
function getPromise(fileName) {
    let p = new Promise((resolve, reject) => {
        //读文件
        fs.readFile(`./data/${fileName}.txt`, 'utf-8', (err, data) => {
            if (err == null) {
                //成功
                resolve(data);
            } else {
                //失败
                reject(err);
            }
        });
    });
    return p;
};

//2.解决需求: 要先读a, 读完a后读b, 读完b后读c.

//开始读取a
getPromise('a').then((data)=>{
    console.log(data);
    //继续读取b
    return getPromise('b');
}).then((data)=>{
    console.log(data);
    //继续读取c
    return getPromise('c');
}).then((data)=>{
    console.log(data);
}).catch((err)=>{
    //以上三个异步操作,只要有任何一个出错,都会执行err
    console.log(err);
});

1.6-Promise对象的all方法

  • all
    • 将多个Promise合并成一个Promise
    • 所有异步全部执行完毕才会执行then方法
const fs = require("fs");

/* 
1. promise实例对象的all方法 : 将多个Promise合并成一个Promise
    * 所有异步全部执行完毕才会执行then方法

2. 解决需求: a , b , c 同时执行完毕
*/


//1.封装一个函数 :  根据文件名生成  文件读取的promise
function getPromise(fileName) {
    let p = new Promise((resolve, reject) => {
        //读文件
        fs.readFile(`./data/${fileName}.txt`, 'utf-8', (err, data) => {
            if (err == null) {
                //成功
                resolve(data);
            } else {
                //失败
                reject(err);
            }
        });
    });
    return p;
};

//2.解决需求: a , b , c 同时执行完毕
let pa = getPromise('a');
let pb = getPromise('b');
let pc = getPromise('c');
//将三个异步操作合并成一个Promise
let pAll = Promise.all([pa,pb,pc]);

//开始读取a
// 三个promise都成功后,才去执行pAll.then的第一个方法.
// 只要有一个失败了,就去执行catch里面的函数.
pAll.then((data)=>{
    console.log(data);//data是一个数组,存储每一个promise的成功结果
}).catch((err)=>{
    console.log(err);
});

1.7-Promise对象的race方法

  • race
    • 将多个Promise合并成一个Promise
    • 任何一个异步 执行完毕就会执行then方法
const fs = require("fs");

/* 
1. promise实例对象的race方法 : 将多个Promise合并成一个Promise
    * 任何一个异步  执行完毕就会执行then方法

2. 解决需求: a , b , c 任意一个成功
*/


//1.封装一个函数 :  根据文件名生成  文件读取的promise
function getPromise(fileName) {
    let p = new Promise((resolve, reject) => {
        //读文件
        fs.readFile(`./data/${fileName}.txt`, 'utf-8', (err, data) => {
            if (err == null) {
                //成功
                resolve(data);
            } else {
                //失败
                reject(err);
            }
        });
    });
    return p;
};

//2.解决需求: a , b , c 同时执行完毕
let pa = getPromise('a');
let pb = getPromise('b');
let pc = getPromise('c');
//将三个异步操作合并成一个Promise
let pAll = Promise.race([pa,pb,pc]);

//开始读取a
// 三个promise任何一个成功,就去执行pAll.then的第一个方法.  (一旦成功一个,其他不再执行)
pAll.then((data)=>{
    console.log(data);//data是第一个执行成功的primise异步结果
}).catch((err)=>{
    console.log(err);
});

1.8-[拓展了解]axios底层基于promise

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
        /* 
        1.axios() : 返回值是promise实例对象
        2.axios() : 底层是基于promise技术封装xhr
        */

        //手写axios底层原理
        function axios(obj){
            return new Promise((resolve,reject)=>{
                //(1).实例化ajax对象
                let xhr = new XMLHttpRequest()
                //(2).设置请求方法和地址ii
                //get请求的数据直接添加在url的后面 格式是 url?key=value
                xhr.open('get', obj.url )
                //(3).发送请求
                xhr.send()
                //(4).注册回调函数
                xhr.onload = function() {
                    resolve( JSON.parse(xhr.responseText) )
                }
            })
        }

        // const p1 = axios()// axios()方法本质是创建promise对象并返回
        // console.log( p1 )//promise实例对象

        Promise.all( [axios({url:'https://autumnfish.cn/api/joke/list?num=10'}) , axios({url:'https://autumnfish.cn/fruitApi/fruits'})] ).then(res=>{
            console.log(res)
        })
        
    </script>
</body>
</html>

02-ES6异步函数async与await

​ 异步函数async相当于是promise语法的 “高级写法”

​ ES2017中引入的更为高级的异步处理机制,async函数,可以让异步的处理变的更加便捷

传送门:阮一峰-async函数

  • 一句话概括: async函数相当于是promise异步函数的另一种高级写法

    • promise虽然解决了异步回调地狱(回调函数层次嵌套)的问题,但是写起来的时候仍然需要嵌套(链式语法嵌套,需要在上一个promise对象的then方法中返回下一个promise)
  • 1.传统的promise异步函数(模拟依次异步读取文件a,b,c)

const fs = require("fs");

/* 
promise实例对象的catch方法 : 用于捕获异步操作的错误信息
*/


//1.封装一个函数 :  根据文件名生成  文件读取的promise
function getPromise(fileName) {
   let p = new Promise((resolve, reject) => {
        //读文件
        fs.readFile(`./data/${fileName}.txt`, 'utf-8', (err, data) => {
            if (err == null) {
                //成功
                resolve(data);
            } else {
                //失败
                reject(err);
            }
        });
    });
    return p;
};

//2.解决需求: 要先读a, 读完a后读b, 读完b后读c.

//开始读取a
getPromise('a').then((data)=>{
    console.log(data);
    //继续读取b
    return getPromise('b');
}).then((data)=>{
    console.log(data);
    //继续读取c
    return getPromise('c');
}).then((data)=>{
    console.log(data);
}).catch((err)=>{
    //以上三个异步操作,只要有任何一个出错,都会执行err
    console.log(err);
});

  • 2.使用async异步函数

  • async语法如下

    • (1)函数前面使用async修饰
    • (2) 函数内部,promise操作使用await修饰
      • await 后面是promise对象, 左侧的返回值就是这个promise对象的then方法中的结果
      • await必须要写在async修饰的函数中,不能单独使用,否则程序会报错
    • (3)async函数内部的异常需要通过try,catch来捕获
const fs = require("fs");

/* 
promise实例对象的catch方法 : 用于捕获异步操作的错误信息
*/


//1.封装一个函数 :  根据文件名生成  文件读取的promise
function getPromise(fileName) {
    let p = new Promise((resolve, reject) => {
        //读文件
        fs.readFile(`./data/${fileName}.txt`, 'utf-8', (err, data) => {
            if (err == null) {
                //成功
                resolve(data);
            } else {
                //失败
                reject(err);
            }
        });
    });
    return p;
};

//2.解决需求: 要先读a, 读完a后读b, 读完b后读c.

// async和await异步函数 :  这两个关键字只能用于函数, 所以用的时候一定要放在函数里面用

/* 
async关键字:  修饰函数。  表示这个函数内部有异步操作。 
await关键字:  等待异步执行完毕。
    (1)await只能用于被async修饰的函数中。  
        只有当await后面的异步操作执行完毕后,才会继续执行后面代码
    (2)await 后面 只能是promise对象
*/

const readFile = async () => {
    
    let data1 = await getPromise('a')
    console.log(data1)

    let data2 = await getPromise('b')
    console.log(data2)

    //async异步函数的错误信息要用try-catch来捕捉
    try {
        let data3 = await getPromise('c')
        console.log(data3)
    } catch (err) {
        console.log(err)

    }
}

readFile()



03-异步函数实际应用场景

1.水果列表

  • 请求地址:https://autumnfish.cn/fruitApi/fruits
  • 请求方法:get
  • 请求参数:
  • 响应内容:json数据

2.水果详情

  • 请求地址: https://autumnfish.cn/fruitApi/fruit/:id
  • 请求方法: get
  • 请求参数:id,在 url 中直接传递
  • 响应内容:json
    • icon:base64 的图片,直接设置给src即可使用

​ 需求: (1)先请求水果列表 (2)默认请求第一个水果详细信息

思考: 这两个ajax有没有顺序要求?

是不是一定要先发送第一个ajax,只有第一个ajax响应了。才可以拿到水果的id来发第二个ajax?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <button class="btn1">按钮1:点我发送ajax</button>
    <br>
    <button class="btn2">按钮2:点我发送ajax</button>

    <!-- 导入axios -->
    <script src="./axios.js"></script>

    <script>
        /* 需求:(1)先请求水果列表 (2)然后默认请求第一个水果详情  */

        //没有使用异步函数
        document.querySelector('.btn1').addEventListener('click',function(){
            //(1)请求水果列表
            axios({
                url:'https://autumnfish.cn/fruitApi/fruits',
                method:'get',
            }).then(res=>{
                //成功回调
                console.log(res)
                //(2)请求水果详情
                axios({
                    url:`https://autumnfish.cn/fruitApi/fruit/${res.data.data[0].id}`,
                    method:'get',
                }).then(res=>{
                    //成功回调
                    console.log(res)
                })
            })
        })

        //使用异步函数
        document.querySelector('.btn2').addEventListener('click',async function(){
            //(1)请求水果列表
            let res1 = await axios({
                url:'https://autumnfish.cn/fruitApi/fruits',
                method:'get'
            })
            console.log(res1)
            
            //(2)请求水果详情
            let res2 = await axios({
                url:`https://autumnfish.cn/fruitApi/fruit/${res1.data.data[0].id}`,
                method:'get'
            })

            console.log(res2)
            
        })
    </script>
</body>
</html>

04-JS执行原理(Event Loop事件循环、微任务、宏任务)

1.1-事件循环Event Loop概念介绍

​ 事件循环Event Loop又叫事件队列,两者是一个概念

  • 1.什么是事件循环 : 浏览器解析执行js代码的一种运行机制(执行规则)
    • 事件循环指的是js代码所在运行环境(浏览器、nodejs)编译器的一种解析执行规则。
      • 在js中讨论事件循环是没有意义的, : 事件循环不属于js代码本身的范畴,而是属于js编译器的范畴
        • 说人话: js代码可以理解为是一个人在公司中具体做的事情, 而 事件循环 相当于是公司的一种规章制度。 两者不是一个层面的概念。

1.2-微任务、宏任务概念介绍

  • 1.微任务与宏任务就属于js代码的范畴

  • 2.js代码主要分为两大类: 同步代码、异步代码

  • 3.异步代码又分为:微任务与宏任务

  • 同步任务:同步任务不需要进行等待,必须立即看到执行结果,比如console

  • 异步任务:异步任务需要等待一定的时候才能看到结果,比如setTimeout、网络请求

  • 异步任务,又可以细分为宏任务和微任务。下面列举目前学过的宏任务和微任务。

任务(代码) 宏/微 任务 环境

1.3-事件循环Event Loop执行机制

  • 1.进入到script标签,就进入到了第一次事件循环.
  • 2.遇到同步代码,立即执行
  • 3.遇到宏任务,放入到宏任务队列里.
  • 4.遇到微任务,放入到微任务队列里.
  • 5.执行完所有同步代码
  • 6.执行微任务代码
  • 7.微任务代码执行完毕,本次队列清空
  • 寻找下一个宏任务,重复步骤1
    • 以此反复直到清空所以宏任务,这种不断重复的执行机制,就叫做事件循环

05-事件循环Event Loop面试题大礼包

  • (1)promise嵌套promise : 先走嵌套的then,后走外层then

    • 原理: promise本身是一个同步的代码(只是容器),只有容器等同步走完了,才会走微任务then()
  • (2)await : 下面的才是微任务, 右边的代码还是立即执行

    • await微任务可以转换成等价的promise微任务分析

      • await 函数名()
        代码块
        //等价于下面代码
        函数名().then(()=>{ 代码块 })
        
      • await fn()
        console.log(1111)
        //等价于
        fn().then(()=>{
            console.log(1111)
        })
        
  • (3)script标签本身是一个宏任务

    • 当页面出现多个script标签的时候,浏览器会把script标签作为宏任务来解析
      • 圈重点 : 解析不代表执行

1.1-第一题

<!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>

        console.log(1)

        setTimeout(function () {
            console.log(2)
        }, 0)

        const p = new Promise((resolve, reject) => {
            resolve(1000)
        })
        
        p.then(data => {
            console.log(data)
        })

        console.log(3)

    </script>
</body>

</html>

1.2-第二题

<!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>

        console.log(1)
        setTimeout(function () {
            console.log(2)
            new Promise(function (resolve) {
                console.log(3)
                resolve()
            }).then(function () {
                console.log(4)
            })
        })

        new Promise(function (resolve) {
            console.log(5)
            resolve()
        }).then(function () {
            console.log(6)
        })
        
        setTimeout(function () {
            console.log(7)
            new Promise(function (resolve) {
                console.log(8)
                resolve()
            }).then(function () {
                console.log(9)
            })
        })
        console.log(10)

    </script>
</body>

</html>

1.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>
        console.log(1)

        setTimeout(function () {
            console.log(2)
        }, 0)

        const p = new Promise((resolve, reject) => {
            console.log(3)
            resolve(1000) // 标记为成功
            console.log(4)
        })

        p.then(data => {
            console.log(data)
        })

        console.log(5)
    </script>
</body>

</html>

1.4-第四题

<!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>
        new Promise((resolve, reject) => {
            resolve(1)

            new Promise((resolve, reject) => {
                resolve(2)
            }).then(data => {
                console.log(data)
            })

        }).then(data => {
            console.log(data)
        })

        console.log(3)
    </script>
</body>

</html>

1.5-第五题

<!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>
        setTimeout(() => {
            console.log(1)
        }, 0)
        new Promise((resolve, reject) => {
            console.log(2)
            resolve('p1')

            new Promise((resolve, reject) => {
                console.log(3)
                setTimeout(() => {
                    resolve('setTimeout2'); //'混淆你的'
                    console.log(4)
                }, 0)
                resolve('p2')
            }).then(data => {
                console.log(data); //'p2'
            })

            setTimeout(() => {
                resolve('setTimeout1'); //'混淆你的'
                console.log(5)
            }, 0)
        }).then(data => {
            console.log(data); //'p1'
        })
        console.log(6)
    </script>
</body>

</html>

1.6-第六题

<!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>
        console.log(1);
        async function fnOne() {
            console.log(2);
            await fnTwo(); // 右结合先执行右侧的代码, 然后等待
            console.log(3);
        }
        async function fnTwo() {
            console.log(4);
        }
        fnOne();
        
        setTimeout(() => {
            console.log(5);
        }, 2000);

        let p = new Promise((resolve, reject) => { // new Promise()里的函数体会马上执行所有代码
            console.log(6);
            resolve();
            console.log(7);
        })

        setTimeout(() => {
            console.log(8)
        }, 0)
        
        p.then(() => {
            console.log(9);
        })
        console.log(10);
    </script>
    <script>
        console.log(11);
        setTimeout(() => {
            console.log(12);
            let p = new Promise((resolve) => {
                resolve(13);
            })
            p.then(res => {
                console.log(res);
            })
            console.log(15);
        }, 0)
        console.log(14);
    </script>
</body>

</html>

1.7-第七题

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>

    <script>
        console.log(1)
        new Promise((resolve, reject) => {
            resolve(2)
        }).then(res => {
            console.log(res)
        })
        setTimeout(() => {
            console.log(3)
        })
        console.log(4)
    </script>

    <script>
        console.log(5)
    </script>

    <script>
       new Promise((resolve,reject)=>{
           resolve(6)
       }).then(res=>{
           console.log(res)
       })
       setTimeout(()=>{
           console.log(7)
       })
       console.log(8)
    </script>

    <script>
        console.log(9)
        setTimeout(()=>{
           console.log(10)
       })
    </script>
</body>

</html>
本文含有隐藏内容,请 开通VIP 后查看