Call function multiple times in the same moment but execute different calls with delay in nodejs

半世苍凉 提交于 2019-12-08 04:02:11

问题


I need to call a function multiple times from different contexts, but i need that each call fires not before that one second has passed after the previous call started.

i'll make an example:

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

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

I want that this log: '1', then after a second '2', then after a second '3', then after a second '4'...

I can't use simple setInterval or setTimeout because this function 'do_something(param)' can be called in the same moment from different sources cause i am working with async function in nodejs. I want that the order of calls is kept, but that they fires with minimum delay of one second.

I think i should add these calls to a queue, and then each second a call is dequeued and the function fires, but i really don't know how to do it in nodejs. Thank you in advance


回答1:


i had to do something like this:

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'
}

in this way i can add tasks to the queue from wherever i want (tasks is a variable of the global context) just calling tasks.push('mytask') and the tasks will be processed one each second following the order they were put in the queue.

However, i didn't really need to do it. I needed because i am using Twilio's apis, and in their doc i read each phone number can send up to an sms for second and no more, but then the support told me they queue requests and send one message each second, so that sending more than a request for second is really not a problem and no sms sending will fail. Hope this will help, byee




回答2:


Coming late to a party

I know I am late, but I had this exact same problem with this exact same technologies.

Your post was very helpful, but it lacked good practices and used Global variables.

My solution

If you are reading this today, I want you to know that after a week of bashing my head I ended up creating a question that lead to two different answers, both capable of helping you:

  • How to delay execution of functions, JavaScript

The queue approach, pioneered by @Arg0n and revamped by me is the closest one to your example, but with none of you drawbacks:

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);

Give it a try and have fun!



来源:https://stackoverflow.com/questions/25109493/call-function-multiple-times-in-the-same-moment-but-execute-different-calls-with

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!