在同一时刻多次调用函数,但在nodejs中执行具有延迟的不同调用

时间:2014-08-03 21:54:04

标签: javascript node.js events queue timing

我需要从不同的上下文中多次调用一个函数,但是我需要在上一次调用开始后的一秒钟之前触发每个调用。

我会举个例子:

var i = 0; 
while(i<50) {
do_something(i)
i++
}

function do_something(a) {
console.log(a)
}

我想要这个日志: '1',然后在第二个'2'之后,然后在第二个'3'之后,然后在第二个'4'之后......

我不能使用简单的setInterval或setTimeout,因为这个函数'do_something(param)'可以在同一时刻从不同的源调用,因为我正在使用nodejs中的异步函数。 我希望保持呼叫的顺序,但它们以最小延迟一秒钟发射。

我想我应该将这些调用添加到队列中,然后每一次调用都会出列并且函数会触发,但我真的不知道如何在nodejs中执行此操作。提前谢谢

2 个答案:

答案 0 :(得分:1)

我必须做这样的事情:

var tasks = [] //global var

var processor = setInterval(function() {
process_task()}, 1000)

function add_task() {
tasks.push('my task') //add task to the end of queue
}

process_task() {
var task_to_use = tasks[0];
tasks.shift() //remove first task in the queue (tasks[0]) 
//do what i need to with the task 'task_to_use'
}

通过这种方式,我可以从我想要的任何地方向队列添加任务(tasks是全局上下文的变量),只需调用tasks.push('mytask'),任务将在订单后每秒处理一次他们被列入队列。

然而,我并不是真的需要这样做。我需要因为我正在使用Twilio的api,并且在他们的文档中我读到每个电话号码可以发送到第二个短信而不是更多,但是然后支持告诉我他们排队请求并每秒发送一条消息,所以发送超过第二个请求确实不是问题,没有短信发送将失败。希望这会有所帮助,byee

答案 1 :(得分:0)

晚会迟到

我知道我迟到了,但我对这些完全相同的技术有同样的问题。

您的帖子非常有用,但它缺乏良好做法并使用了全局变量。

我的解决方案

如果您今天正在阅读本文,我希望您知道,经过一周的抨击,我最终创建了一个问题,导致两个不同的答案,都能够帮助您:

由@ Arg0n开创并由我改造的队列方法是最接近你的例子,但没有任何缺点:

let asyncFunc = function(url) {
  return new Promise((resolve, reject) => {
    setTimeout(function() {
      resolve({
        url: url,
        data: "banana"
      });
    }, 5000);
  });
};

let delayFactory = function(args) {
  let {
    delayMs
  } = args;
  let queuedCalls = [];
  let executing = false;

  let queueCall = function(url) {
    return new Promise((resolve, reject) => {

      queuedCalls.push({
        url,
        resolve,
        reject
      });

      if (executing === false) {
        executing = true;
        nextCall();
      }
    });
  };

  let execute = function(call) {

    console.log(`sending request ${call.url}`);

    asyncFunc(call.url)
      .then(call.resolve)
      .catch(call.reject);

    setTimeout(nextCall, delayMs);
  };

  let nextCall = function() {
    if (queuedCalls.length > 0)
      execute(queuedCalls.shift());
    else
      executing = false;
  };

  return Object.freeze({
    queueCall
  });
};

let myFactory = delayFactory({
  delayMs: 1000
});

myFactory.queueCall("http://test1")
  .then(console.log)
  .catch(console.log);

myFactory.queueCall("http://test2")
  .then(console.log)
  .catch(console.log);

myFactory.queueCall("http://test3")
  .then(console.log)
  .catch(console.log);

试一试,玩得开心!