promise控制并发请求数量

2023-05-16

有这样一个面试题目:
有 8 个图片资源的 url,已经存储在数组 urls 中(即urls = [‘http://example.com/1.jpg’, …., ‘http://example.com/8.jpg’]),而且已经有一个函数 function loadImg,输入一个 url 链接,返回一个 Promise,该 Promise 在图片下载完成的时候 resolve,下载失败则 reject。

但是我们要求,任意时刻,同时下载的链接数量不可以超过 3 个。

请写一段代码实现这个需求,要求尽可能快速地将所有图片下载完成。

已有代码如下:

var urls = [
'https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg', 
'https://www.kkkk1000.com/images/getImgData/gray.gif', 
'https://www.kkkk1000.com/images/getImgData/Particle.gif', 
'https://www.kkkk1000.com/images/getImgData/arithmetic.png', 
'https://www.kkkk1000.com/images/getImgData/arithmetic2.gif', 
'https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg', 
'https://www.kkkk1000.com/images/getImgData/arithmetic.gif', 
'https://www.kkkk1000.com/images/wxQrCode2.png'
];
function loadImg(url) {
    return new Promise((resolve, reject) => {
        const img = new Image()
        img.onload = function () {
            console.log('一张图片加载完成');
            resolve();
        }
        img.onerror = reject
        img.src = url
    })
};

看到这个题目的时候,脑袋里瞬间想到了高效率排队买地铁票的情景,那个情景类似下图:
在这里插入图片描述
上图这样的排队和并发请求的场景基本类似,窗口只有三个,人超过三个之后,后面的人只能排队了。

于是想到解题的大体思路如下:
首先我们对给出的loadImg函数进行封装,封装的目的有2个:

  1. 对每次调用该函数加载图片时进行计数,每调用一次数量加1,以保证同时请求的数量不超过要求的数量。
  2. 在图片加载成功或失败的回调函数中计数减1,表示对某一个图片的处理已经完成,空出了一个位置。然后进行判断,看当前请求的数量是否小于限制数量,并且urls数组里面还有元素,条件成立的话就递归调用本函数。

代码如下:

var total = 3, count = 0

function counterLoad() {
     count++
     loadImg(urls.shift())
  .then(() => {
      count--
      if(count<total && urls.length) {
          counterLoad()
      }
  })
  .catch(err => {
      console.log('图片加载失败', err)
      count--
      if(count<total && urls.length) {
          counterLoad()
      }
  })
}

for(var i=0; i<total; i++) {
    counterLoad()
}

此题其他解法可参考原文Promise面试题3控制并发

类比上面的解决办法,可按如下方式并发多个请求

// 假如有5个api,每次并发的数量限制为2个,尽快获取所有数据
      
        // 数组中的元素值都是api配置对象,apiName为一个函数的引用, apiParams为该函数的参数
        var apis = [
            {
                apiName: getName,
                apiParams: {
                    gentle: 'male',
                    age: 18
                }
            },
            {
                apiName: getName,
                apiParams: {
                    gentle: 'male',
                    age: 18
                }
            },
            {
                apiName: getName,
                apiParams: {
                    gentle: 'male',
                    age: 18
                }
            },
            // ......
        ] 
        var total = 2 //并发的数量限制
        var count = 0 // 当前正在进行的请求数量


        function getData(apiConfig) {
            return new Promise((resolve, reject) => {
                apiConfig.apiName(apiConfig.apiParams).then((res) => {
                    resolve(res)
                }).catch(err => {
                    console.log('请求出错', err)
                    // 这里不管请求成功或出错,都调用一下resolve,这样方便外层promise的统一处理计数减1
                    resolve()
                })
            })
        }

        function CountLimitedRequest() {
            count++
            console.log('当前正在进行的请求数量为',count)
            if(count<=total && apis.length) {
                getData(apis.shift())
                    .then(() => {
                        // 每个请求完成之后count--
                        count--
                        // 递归调用CountLimitedRequest执行下一个请求
                        CountLimitedRequest()
                    })
            }
        }

        function start() {
            // 同时启动total个请求
            for(var i=0; i<total; i++) {
                CountLimitedRequest()
            }
        }

参考文章:Promise面试题3控制并发

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

promise控制并发请求数量 的相关文章

  • 关于 Node.js Promise then 和 return?

    我对承诺感到困惑 I use 那么就答应没有返回像这样 new Promise resolve reject gt resolve 1 then v1 gt console log v1 new Promise resolve reject
  • AWS Lambda 提前结束(没有任何显式返回或回调)

    我在放入 AWS Lambda 中的一些 Node js 代码时遇到了一些问题 我需要进行几个异步调用 虽然第一个调用的行为符合我的预期 但 lambda 函数在第二个调用完成之前终止 返回值为 null 这让我认为 lambda 正在执行
  • Promise 构造函数回调的主体何时执行?

    假设我有以下代码构造一个Promise function doSomethingAsynchronous return new Promise resolve gt const result doSomeWork setTimeout gt
  • 如何异步处理未处理的承诺拒绝?

    我正在尝试解决我面临的有关异步 等待和承诺的问题 我设法将问题归结为以下代码 async function sleep ms number return new Promise resolve gt setTimeout resolve m
  • 何时不使用承诺[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在阅读了数十篇关于 es6 Promise 有多伟大以及为什么我们应该实现它们的文章之后 我有这样的感觉 ALL我的 不平凡的 JavaScri
  • 为 Promise 编写循环的正确方法。

    如何正确构造循环以确保满足以下条件承诺电话和被束缚的记录器 log res 通过迭代同步运行 蓝鸟 db getUser email then function res logger log res this is a promise 我尝
  • 返回承诺与在承诺内返回未定义之间的区别

    我不太确定我是否理解这两种常见场景之间的区别 假设我们有这个 user save then function val anotherPromise1 val then function val anotherPromise2 val cat
  • 在 Smalltalk/Pharo 中创建以块作为参数的键值消息

    我有一个场景 一个类拥有两个互斥的实例变量 即一次只能实例化一个 准确地说 我有一个 Promise 类 尝试将 Promise 添加到 Pharo 它包含 PromiseError 和 PromiseValue 实例变量 然后我想实现 t
  • 从 Promise 块返回函数值

    我正在尝试编写一个函数 使用 WebdriverJS lib 来迭代元素列表 检查名称并构建与该名称对应的 xpath 定位器 我这里简化了xpath定位器 大家不用关注 我在这里面临的问题是 1 调用该函数返回未定义 据我了解 这是因为
  • 如何沿着 Parse Promise 链传递额外数据[重复]

    这个问题在这里已经有答案了 在我的 Parse Cloude 代码中 我需要运行几个连续的查询 每个查询都使用 find Example var promise firstQuery get objectId then function r
  • everyauth 承诺是什么?

    我不明白 everyauth 承诺是什么 我发现我需要返回一个 Promise 对象或用户 但是 everyauth Promise 是什么 当您有一个执行身份验证但异步执行的函数时 它非常有用 您不能直接从函数返回用户信息 因为您必须等待
  • Javascript 异步函数的“await”的正确心理模型:生成器的“yield”与“promise.then()”?

    生成器的 Yield 与 Promise then 哪个是理解 等待 的更正确的心理模型 属性比较 通过使用调试器单步执行下面的代码片段来推断 await wait 不会暂停 暂停正在运行的异步函数的执行 正在运行的异步函数 运行到完成 当
  • 在 for 循环内顺序执行 Promise

    我正在努力将两个承诺链接到一个循环中 以便第二个承诺在第一个承诺得到解决之前不会启动 我看到了一个减少的例子 还无法让它工作 如果我这样做 就像我现在所做的那样 代码会并行执行 就像这样 所有异步请求都会被触发 当然结果会很混乱 请看一下
  • Angular2 中 Http 的 Promise 与 Observable? [复制]

    这个问题在这里已经有答案了 本质上 正如标题所说 是否有任何理由使用可观察的承诺 https stackoverflow com questions 37364973 angular 2 promise vs observable为了进行
  • JavaScript 中的 Promise 有什么意义?

    一个承诺是一个 可能现在可用 或将来可用 或永远不可用的值 来源 MDN 假设我有一个想要处理图片的应用程序 图片已加载 例如在算法在后台使用它之后 或某种其他类型的延迟 现在我想检查一下图片是否可以在future 通过使用承诺 而不是回调
  • Deferred 延长了 Promise

    如何实现延期 Promise 的 Deferred Promise 在需要典型 Promise 的情况下 扩展 Promise 以实现类型安全使用非常重要 实施后 export class Deferred
  • 如何使用promise来避免回调地狱? [复制]

    这个问题在这里已经有答案了 所以我有一个帖子集合 id String comments String id of Comments links String id of Links 评论 id 字符串 评论 字符串 链接 id 字符串 链接
  • Javascript,使用 Promises 在 Array.reduce 中上传多个文件,怎么样?

    演变自Javascript 用Promises拼接FileReader处理大文件 怎么样 https stackoverflow com questions 38815140 javascript spliced filereader fo
  • 您在需要流的地方提供了无效的对象。您可以提供 Observable、Promise、Array 或 Iterable

    假设我有以下函数引用 const externalRequests params gt Rx Observable zip externalApi1 params externalApi2 params and const internal
  • 期货与承诺

    我对未来和承诺之间的区别感到困惑 显然 他们有不同的方法和内容 但实际用例是什么 Is it 当我管理一些异步任务时 我使用 future 来获取 未来 的值 当我是异步任务时 我使用 Promise 作为返回类型 以允许用户从我的 Pro

随机推荐