为什么会先输出异步函数里的代码,而不是先输出异步外的代码

为什么会先输出异步函数里的代码,而不是先输出异步外的代码

<!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>
    <style>
        .ad {
            display: block;
            width: 300px;
            height: 150px;
            margin: 0 auto;
        }

        .none {
            display: none;
        }
    </style>
</head>

<body>

    <img id="ad" src="https://img1.sycdn.imooc.com/climg//6264ff5c0916217006960344-360-202.png" alt="前端体系课" class="ad none">
    <script>
        // 等待异步操作
        // await跟一个异步操作,其实异步操作就是Promise对象。它们会共同构成一个表达式,有值!
        // async的机制:async函数中的代码有先后关系,await会阻塞该async函数中代码的执行,async函数外的代码不受影响。async函数内部是同步执行的,它本身是异步的。所以会先输出"async外的代码"
        // async函数内部是同步执行的,外部是异步的。先输出最后的输出
        function wait(ms) {
            return new Promise(resolve => {
                setTimeout(resolve, ms);
            })
        }

        async function ad() {
            // 疑问处:视频里老师说ad函数是异步的,在整体下,也会先输出异步函数外边的,再输出异步函数里的。这里为什么会先输出了"async内的代码"呢?
            console.log("async内的代码");
            const $ad = document.getElementById("ad");
            // await后面的wait函数 返回是Promise对象
            await wait(1000);
            // 程序堵塞住,等待1s,等待完显示广告
            $ad.classList.remove("none");

            await wait(2000);
            // 程序堵塞住,等待2s,等待完隐藏广告
            $ad.classList.add("none");
        }

        ad();
        console.log("async外的代码");
        // —————————————————————————————————————————————————————————
        // 上边那四行代码,等价于下边的:
        // wait(1000).then(() => {
        //     $ad.classList.remove("none");
        //     return wait(2000);
        // }).then(() => {
        //     $ad.classList.add("none");
        // })
    </script>
</body>

</html>

视频里老师说ad函数是异步的,在整体下,也会先输出异步函数外边的,再输出异步函数里的。这里为什么会先输出了"async内的代码"呢?


正在回答

登陆购买课程后可参与讨论,去登陆

1回答

同学你好,不是这样理解的,我们可以看一个简单的小例子,如下代码:

https://img1.sycdn.imooc.com/climg/62ccda60097f67ec04230156.jpg

打印结果为:

https://img1.sycdn.imooc.com/climg/62ccda7e0939441d02170047.jpg

可以看到:async函数timeout调用了,但是没有任何输出,我们打印一下这个timeout()语句;改成console.log(timeout()),参考如下:

https://img1.sycdn.imooc.com/climg/62ccdb4109a1cadf03290049.jpg

可以看出,async函数返回值为promise对象,如果要获取到promise返回值,应该用then方法

https://img1.sycdn.imooc.com/climg/62ccdbda09ed9d5a03990206.jpg

https://img1.sycdn.imooc.com/climg/62ccdbe8098a8d9701890044.jpg

由此可以看出,先执行的同步然后执行的异步;

同学可以再试着重新理解理解;

祝学习愉快~

  • qq_慕仰20210716 提问者 #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>
            async function timeout() {
                console.log("最先输出的");//新加的语句
                return 'hello world';
            }
            // console.log(timeout());
            // async函数返回值为promise对象,如果要获取到promise返回值,应该用then方法。结果:Promise {<fulfilled>: 'hello world'}
    
            timeout().then(result => {
                console.log(result);
            })
            // 结果: hello world
    
            console.log("虽然在后面,但是我先执行");
    
            // 提问内容:
            // 我又加了一个输出语句:"最先输出的"。
            // 好像懂了一点点:我的理解程序最开始调用timeout函数。调用成功之后先输出"最先输出的"。至此是第一个输出。然后返回"hello world"结束。
            // 但这个时候,程序外边的同步的代码,自然会先输出"虽然在后面,但是我先执行"。至此是第二个输出。
            // 因为timeout函数返回的是一个Promise对象,所以可以调用then方法,默认是成功状态的,return的值是"hello world",所以这个"hello world"就会传给then方法赋值给形参result,自然可以输出"hello world"。至此是第三个输出。因为Promise对象是异步,所以后输出吗老师。
        </script>
    </body>
    
    </html>

    老师,我写了一下自己的理解,您看看对不对。

    下边这个您看看是不是我可以对比着理解,都是写在异步函数里,所以都会后输出


    <!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("我是异步代码,无论如何都是我后输出");
            }, 0)
            console.log("我是同步代码,先输出,哪怕你是0s,也是我先");
        </script>
    </body>
    
    </html>


    2022-07-12 12:04:43
  • imooc_慕慕 回复 提问者 qq_慕仰20210716 #2

    同学你好,async异步函数,需要使用return 返回值,同学此处添加的代码,没有意义,日常代码也不会这样写,并且不能体现出异步后执行;打印的效果和普通函数一样;所以不要太纠结;

    new Promise()本身是同步,它的then()是异步;参考代码如下:

    https://img1.sycdn.imooc.com//climg/62cd105709ba2f4b04290111.jpg

    https://img1.sycdn.imooc.com//climg/62cd107d098ebd3501470064.jpg

    添加then()方法;

    https://img1.sycdn.imooc.com//climg/62cd10a5096bed8d04430197.jpg

    https://img1.sycdn.imooc.com//climg/62cd10bb09db1e6101460083.jpg


    第二段代码理解是可以的;

    祝学习愉快~


    2022-07-12 14:14:08
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师