【一篇就够】异步相关(一)

98 阅读4分钟

 

1. promise 和 async await区别

  • 概念

Promise 是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更合理更强大,简单地说,Promise好比容器,里面存在着一些未来才会执行完毕(异步)的事件和结果,而这些结果一旦生成是无法改变的。

        async await 也是异步编程的一种解决方案,他遵循的是Generator 函数的语法糖,他拥有内置执行器,不需要额外的调用直接会自动执行并输出结果,它返回的是一个Promise对象。

  • 两者的区别

  1. Promise的出现解决了传统callback函数导致的“地域回调”问题,但它的语法导致了它向纵向发展行成了一个回调链,遇到复杂的业务场景,这样的语法显然也是不美观的。而async await代码看起来会简洁些,使得异步代码看起来像同步代码,await的本质是可以提供等同于”同步效果“的等待异步返回能力的语法糖,只有这一句代码执行完,才会执行下一句。
  2. async await与Promise一样,是非阻塞的。
  3. async await是基于Promise实现的,可以说是改良版的Promise,它不能用于普通的回调函数。

2. defer和async区别

        区别主要在于一个执行时间,defer会在文档解析完之后执行,并且多个defer会按照顺序执行,而async则是在js加载好之后就会执行,并且多个async,哪个加载好就执行哪个

  • 解析

        在没有defer或者async的情况下:会立即执行脚本,所以通常建议把script放在body最后

    <script src="script.js"></script>

        async: 有async的话,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。
但是多个js文件的加载顺序不会按照书写顺序进行

    <script async src="script.js"></script>

        derer: 有derer的话,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成,并且多个defer会按照顺序进行加载。

    <script defer src="script.js"></script>

​编辑

  • 总结 

    • defer和async都是异步加载外部JS文件
    • defer和async的差别在于脚本下载完成之后何时执行,显然defer是更接近需求的
    • async不保证脚本的执行顺序
    • async在外部JS加载完毕之后,浏览器空闲时触发执行
    • defer是在外部JS加载完毕之后,整个文档解析完成后触发执行
    • defer更像是将

3. 同步和异步

  • 同步

        指在主线程上排队执行的任务,只有前一个任务执行完后才能继续执行下一个任务。

        也就是调用开始,必须调用返回结果才能继续往后执行。程序的执行顺序和任务的排列顺序是一致的。

  • 异步

        异步任务是指不进入主线程,而进入任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才能进入主线程。      

        

        每一个任务有一个或多个 回调函数。前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行。

       

        任务的执行和任务的排列是不一致的,是异步的。

        我们常用的setTimeout和setInterval函数,Ajax都是异步操作。

4. 实现异步的方法

回调函数(Callback)、事件监听、发布订阅、Promise/A+、生成器Generators/ yield、async/await

  1. JS 异步编程进化史:callback -> promise -> generator -> async + await
  2. async/await 函数的实现,就是将 Generator 函数和自动执行器,包装在一个函数里。
  3. async/await可以说是异步终极解决方案了。

        (1)async/await函数相对于Promise,优势体现在:                                                   

                   处理 then 的调用链,能够更清晰准确的写出代码;并且也能优雅地解决回调地狱问题。

        当然async/await函数也存在一些缺点,因为 await 将异步代码改造成了同步代码,如果多个异步代码没有依赖性却使用了 await 会导致性能上的降低,代码没有依赖性的话,完全可以使用 Promise.all 的方式。

         (2)async/await函数对 Generator 函数的改进,体现在以下三点:

                    内置执行器。 Generator 函数的执行必须靠执行器,所以才有了 co 函数库,而 async 函数自带执行器。也就是说,async 函数的执行,与普通函数一模一样,只要一行

                    更广的适用性。 co 函数库约定,yield 命令后面只能是 Thunk 函数或 Promise 对象,而 async 函数的 await 命令后面,可以跟 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)

                    更好的语义。 async 和 await,比起星号和 yield,语义更清楚了。async 表示函数里有异步操作,await 表示紧跟在后面的表达式需要等待结果。