限制Node.js中的请求

r3i60tvu  于 2022-12-26  发布在  Node.js
关注(0)|答案(8)|浏览(241)

我有一个数组,我可以用foreach方法循环访问它。

data.forEach(function (result, i) {

     url = data[i].url;

     request(url);

});

request函数向给定的url发出http请求,但是同时发出所有这些请求会导致各种各样的问题。
所以我想我应该通过引入某种计时器来放慢速度。
但是我不知道如何将forach循环与setTimeOut/setInterval结合起来
请注意,我是在服务器(nodejs)上而不是在浏览器上执行此操作的。
谢谢你的帮助。

3duebb1j

3duebb1j1#

由于您的问题是全局性的,您应该调整您的request函数,使其一次只运行5个请求-使用全局静态计数器。

function request(url, callback) {
    ajax(url, callback);
}

现在使用类似于

var count = 0;
var waiting = [];
function request(url, callback) {
    if (count < 5) {
        count++;
        ajax(url, function() {
            count--;
            if (waiting.length)
                request.apply(null, waiting.shift());
            callback.apply(this, arguments);
        });
    } else
        waiting.push(arguments);
}
mzaanser

mzaanser2#

data.forEach(function (result, i) {

     url = data[i].url;

     setTimeout(
         function () {
              request(url);
         }, 
         1000 * (i + 1) // where they will each progressively wait 1 sec more each
     );

 });
wooyq4lh

wooyq4lh3#

而不是setTimeout可以让它们按顺序运行。我假设request()函数中有一个callback参数。

function makeRequest(arr, i) {
    if (i < arr.length) {
        request(arr[i].url, function() { 
                                i++; 
                                makeRequest(arr, i); 
                            });
    }
}

makeRequest(data, 0);

如果请求之间需要多一点时间,则将setTimeout添加到回调中。

function makeRequest(arr, i) {
    if (i < arr.length) {
        request(arr[i].url, function() { 
                                i++; 
                                setTimeout(makeRequest, 1000, arr, i); 
                            });
    }
}

makeRequest(data, 0);
qnakjoqk

qnakjoqk4#

你可以延迟调用使用setTimeout.下面的代码将确保每个请求得到调用后timerMultiPlier毫秒从它的前一个请求.

var timerMultiPlier = 1000;
data.forEach(function (result, i) {
     setTimeout(function(){
           url = data[i].url;         
           request(url);
   }, timerMultiPlier*i );

});
trnvg8h3

trnvg8h35#

上面的许多解决方案,虽然对一些请求是可行的,但在处理成千上万的请求时,却毫无疑问地阻塞和阻塞了页面。与其将所有的计时器一个一个地排队,不如将每个计时器一个接一个地排队。如果你的目标是有一个漂亮的代码,有很多糖和“好东西”,那么下面就是适合你的解决方案。

function miliseconds(x) { return x }
function onceEvery( msTime ){
    return {
        doForEach: function(arr, eachF){
            var i = 0, Len = arr.length;
            (function rekurse(){
                if (i < Len) {
                    eachF( arr[i], i, arr );
                    setTimeout(rekurse, msTime);
                    ++i;
                }
            })();
        }
    };
}

漂亮、蓬松的糖衣用法:

onceEvery(
    miliseconds( 150 )
).doForEach(
    ["Lorem", "ipsum", "dolar", "un", "sit", "amet"],
    function(value, index, array){
        console.log( value, index );
    }
)

function miliseconds(x) { return x }
function onceEvery( msTime ){
    return {
        doForEach: function(arr, eachF){
            var i = 0, Len = arr.length;
            (function rekurse(){
                if (i < Len) {
                    eachF( arr[i], i, arr );
                    setTimeout(rekurse, msTime);
                    ++i;
                }
            })();
        }
    };
}
t5zmwmid

t5zmwmid6#

您可以通过索引来抵消每个项的执行延迟,如下所示:

data.forEach(function (result, i) { 
  setTimeout(function() {
    url = data[i].url; 
    request(url);
  }, i * 100);
});

这将使每次迭代比上一次迭代晚100毫秒执行,您可以将100更改为任何您想要更改延迟的数字。

myzjeezk

myzjeezk7#

对这些问题做了一些补充,只是为了知识基础。
已创建异步版本,但没有递归。

function onceEvery(msTime) {
  return {
    doForEach: function (eachFunc, paramArray) {
      var i = 0, Len = paramArray.length;
      (function rekurse() {
        if (i < Len) {
          eachFunc(paramArray[i], i, paramArray);
          setTimeout(rekurse, msTime);
          ++i;
        }
      })();
    },
    doForEachAsync: async function (eachFunc, paramArray, staticParamenters) {
      var i = 0, Len = paramArray.length;
      while (i < Len) {
        await (async function rekurse() {
          await eachFunc(paramArray[i], staticParamenters);
          setTimeout(() => { }, msTime);
          ++i;
        })();
      }
    }
  };
}

module.exports = {
  onceEvery
};

将此代码放入一个.js中并调用,如下所示:

await throttle.onceEvery(100).doForEachAsync(loadJobFunction, arrayParam, { staticParam1, staticParam2, staticParam3 });
hsgswve4

hsgswve48#

使用async / await进行快速节流的一种非常简单的解决方案是创建一个承诺,例如:

const wait = (delay) => new Promise((resolve, _) => {
  setTimeout(() => resolve(true), delay)
})

然后在需要暂停时等待它(在async函数中):

//... loop process
  await wait(100)

注意:你需要使用一个for循环来完成这个任务,forEach不会等待。

相关问题