async和await概念 浏览器EventLoop事件循环 以及一些遇到的相关面试题

本文介绍了async/await的使用,强调了其在优化Promise链式调用中的作用,以及注意事项,如await必须在async函数内使用。接着探讨了JavaScript的EventLoop事件循环机制,包括微任务和宏任务的概念,解释了为何需要微任务队列和宏任务队列,以及它们如何影响异步执行的顺序。最后,列举了一些相关的面试题目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

取代then函数, 来提取Promise的值

Promise链式调用

// 目标: 使用Promise的链式调用解决问题
// 前提: axios函数在原地返回的就是一个Promise对象
let pname = ''
axios.get('http://ajax-api.itheima.net/api/province').then(res => {
    // 2. 获取某个省, 对应的城市列表
    pname = res.data.data[5];
    return axios.get(`http://ajax-api.itheima.net/api/city?pname=${pname}`)
}).then(res => {
    // 3. 获取某个市, 对应的地区列表
    let cname = res.data.data[0]
    return axios.get(`http://ajax-api.itheima.net/api/area?pname=${pname}&cname=${cname}`)
}).then(res => {
    console.log(res);
})

async await语法

async function 函数名() {
    const result = await Promise对象
    // 拿到Promise对象内成功的结果继续向下执行
}

示例

// 目标: 掌握下async和await语法
// 目的: 用await取代then函数, 来提取成功的值在原地
let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功的值')
    }, 2000)
})
​
// 普通函数: async+await
async function fn() {
    const result = await p
    console.log(result)
}
fn()
​
// 箭头函数: async+await
const myFn = async () => {
    const result = await p
    console.log(result)
}
myFn()

注意事项

  1. await 必须用在async修饰的函数内

  2. async修饰后, 此函数为异步函数

  3. await之后一般跟promise

  1. await不能捕获失败结果, 需要使用try+catch关键字捕获

  2. /*
        try和catch语法
        try {
            // 这里放可能在执行中报错的代码
            // 如果报错会终止代码继续执行, 直接跳转进catch里执行
        } catch (err) {
            // err接收try大括号内报错抛出的异常代码
        }
    ​
    */
    let p = new Promise((resolve, reject) => {
        setTimeout(() => {
            // resolve(1)
            reject(new Error('失败'))
        }, 2000)
    })
    ​
    async function myFn() {
        try {
            const res = await p
            console.log(res);
        } catch (err) {
            console.error(err)
        }
    }
    myFn()

使用async await优化回调地狱

// 目标: 使用Promise的链式调用解决问题
// 前提: axios函数在原地返回的就是一个Promise对象
async function f() {
  const provinces = await axios.get('http://ajax-api.itheima.net/api/province')
  const pname = provinces.data.data[5]
  const citys = await axios.get(`http://ajax-api.itheima.net/api/city?pname=${pname}`)
  const cname = citys.data.data[0]
  const areas = await axios.get(`http://ajax-api.itheima.net/api/area?pname=${pname}&cname=${cname}`)
    return areas
}
f()

EventLoop事件循环

JavaScript 是一门单线程执行的脚本语言。也就是说,同一时间只能做一件事情。

javaScript要运行在宿主环境中(浏览器,nodejs)下。浏览器内部有执行js代码的引擎(V8引擎)

排队是任务是以事件及其回调的方式存在的。

当事件(用户的点击,图片的成功加载)发生时,将其回调添加到任务队列;主线程上的任务完成之后,就会从任务队列中取出任务来执行,

话术

浏览器中的EventLoop(这个比较偏理论一点,我是这样理解的):js是单线程的,一次只能做一件事。js在浏览器这个宿主环境中运行。浏览器是多线程的,用户交互,定时器,网络请求等等浏览器中的事件会产生对应的任务,任务多了要在任务队列中排队,浏览器的主线程依次取出任务来执行,此过程不断重复从而形成一个循环,称为eventLoop。

概念_微任务和宏任务

异步任务

不是马上执行,是放入到队列中等待;

如果所有的任务都要按序等待,那么也不行,需要有一个能插队的机制。所以又将异步任务分为微任务和宏任务,同时对应微任务队列和宏任务队列。

当主线程空闲时,先执行微任务队列中的任务,再去执行宏任务队列中的任务。

JavaScript为什么要有微任务? - 知乎

微任务队列和宏任务队列

微任务代码(js语法)

  • Promise对象.then()

(.then( )里面的是微任务)

宏任务代码(宿主环境)

  • script

  • dom事件

  • ajax

  • setTimout

经典面试题

<script>
    console.log(1);
    setTimeout(() => {
        console.log(2);
    }, 0)
    console.log(3);
</script>
<script>
    console.log(4);
    setTimeout(() => {
        console.log(5);
    }, 0)
    console.log(6);
</script>
<script>
    async function async1 () {
        console.log('1');
        await async2();
        console.log('2');
    }
​
    async function async2 () {
        console.log('3');
    }
​
    console.log('4');
​
    setTimeout(function () {
        console.log('5');
    }, 0);
​
    async1();
​
    new Promise(function (resolve) {
        console.log('6');
        resolve();
    }).then(function () {
        console.log('7');
    });
​
    console.log('8');
​
</script>

4 1 3 6 8 2 7 5

<script>
    console.log(1);
    async function fnOne() {
        console.log(2);
        await fnTwo(); // 右结合先执行右侧的代码, 然后等待
        console.log(3);
        //await等于promis
        // new Promise((resolve,reject)=>{
        //     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>

6 7 10 3 9 11 14 8 12 15 13 5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值