袋鼠网络

你知道Async/Await是如何通过同步的方式实现异步?

袋鼠网络 2021-07-28
<span style="color: rgb(74, 74, 74); font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, " helvetica="" neue",="" "pingfang="" sc",="" "hiragino="" sans="" gb",="" "microsoft="" yahei="" ui",="" yahei",="" arial,="" sans-serif;="" letter-spacing:="" 0.544px;="" white-space:="" pre-line;"="">这个题目本身不是特别难,只能说是作为社招的基础面试题,但是如果想回答好这道题并且惊艳面试官也不是很容易。不信接着往下看:

1、概括的说

await 只能在 async 函数中使用,可以把 async 看成将函数返回值使用 Promise.resolve() 包裹了下。

我们来看一下代码实例:



上面代码会先打印 finish 然后再打印 object 。因为 await 会等待 sleep 函数 resolve ,所以即使后面是同步代码,也不会先去执行同步代码再来执行异步代码。

2、亮点回答

意思就是说:执行代码是一行一行的往下走(即所谓的同步),

还是举个例子:

显然是不行的,因而 js 设计了异步,即 发起网络请求(诸如 IO 操作,定时器),由于需要等服务器响应,就先不理会,而是去做其他的事儿,等请求返回了结果的时候再说(即异步)。

之前这种函数嵌套,大量的回调函数,使代码阅读起来晦涩难懂,不直观,形象的称之为回调地狱(callback hell),所以为了在写法上能更通俗一点,es6+陆续出现了 Promise、Generator、Async/await,力求在写法上简洁明了,可读性强。

所以了解 async/await 就不得不讲一讲 Generator,以后我们可以讲一下这个。

终于找到源头了:单向链表,以后可以讲一下这个。

现在再来看看async/await 的特点:

  • async/await 是参照 Generator 封装的一套异步处理方案,可以理解为 Generator 的语法糖,

    而 Generator 又依赖于迭代器Iterator,

    而 Iterator 的思想呢又来源于单向链表,

    我们看一下wiki的说明:链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序储存数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序储存,链表在插入的时候可以达到 o(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要 o(n)的时间,而顺序表响应的时间复杂度分别是 o(logn)和 o(1)。

     

    • 无需预先分配内存

    • 插入/删除节点不影响其他节点,效率高(典型的例子:git commit)


    单链特点:节点的链接方向是单向的;相对于数组来说,单链表的的随机访问速度较慢,但是单链表删除/添加数据的效率很高。

    Iterator 翻译过来就是迭代器(遍历器)让我们先来看看它的遍历过程(类似于单向链表):

    • 一个对象要变成可迭代的,必须实现 @@iterator 方法,即对象(或它原型链上的某个对象)必须有一个名字是 Symbol.iterator 的属性(原生具有该属性的有:字符串、数组、类数组的对象、Set 和 Map):

      Generator:生成器对象是生成器函数(GeneratorFunction)返回的,它符合可迭代协议和迭代器协议,既是迭代器也是可迭代对象,可以调用 next 方法,但它不是函数,更不是构造函数.

      我们来总结一下 Generator 的本质,暂停,它会让程序执行到指定位置先暂停(yield),然后再启动(next),再暂停(yield),再启动(next),而这个暂停就很容易让它和异步操作产生联系,因为我们在处理异步时:开始异步处理(网络求情、IO 操作),然后暂停一下,等处理完了,再该干嘛干嘛。不过值得注意的是,js 是单线程的(又重复了三遍),异步还是异步,callback 还是 callback,不会因为 Generator 而有任何改变。

      3.4 Async/Await

      觉得这样是不是可以清晰点了。

       

电话咨询 置顶