在写这篇文章的时候我有点犹豫,因为先前写过一篇相似的,一道对于并发管制的面试题,只不过那篇文章只给出了一种解决方案,起初在网上又陆续找到两种解决方案,说来惭愧,钻研问题总是浅尝辄止,所以明天便放在一起,借着这道面试题再从新梳理一下。
题目是这样的:
有 8 个图片资源的 url,曾经存储在数组 urls 中(即 urls = [‘http://example.com/1.jpg’, ….,‘http://example.com/8.jpg’]),而且曾经有一个函数 function loadImg,输出一个 url 链接,返回一个 Promise,该 Promise 在图片下载实现的时候 resolve,下载失败则 reject。
然而咱们要求,任意时刻,同时下载的链接数量不能够超过 3 个。
请写一段代码实现这个需要,要求尽可能疾速地将所有图片下载实现。
已有代码如下:
看到这个题目的时候,脑袋里霎时想到了高效率排队买地铁票的情景,那个情景相似下图 上图这样的排队和并发申请的场景根本相似,窗口只有三个,人超过三个之后,前面的人只能排队了。
首先想到的便是利用递归来做,就如这篇文章采取的措施一样,代码如下:
以上是最惯例的思路,我将加载图片的函数 loadImg 封装在 bao 函数内,依据条件判断,是否发送申请,申请实现后持续递归调用。
以上代码所有逻辑都写在了同一个函数中而后递归调用,能够优化一下,代码如下:
下面代码将一个递归函数拆分成两个,一个函数只负责计数和发送申请,另外一个负责调度。
这里的申请既然曾经被封装成了 Promise,那么咱们用 Promise 和 saync、await 来实现一下,代码如下:
大抵思路是,遍历执行 urls.length 长度的申请,然而当申请并发数大于限度时,超过的申请用 await 联合 promise 将其阻塞,并且将 resolve 填充到 lock 数组中,继续执行,并发过程中有图片加载实现后,从 lock 中推出一项 resolve 执行,lock 相当于一个叫号机;以上代码能够优化为: