简体   繁体   中英

how call a function every 5 minute inside array in javascript

i have a array with any params for example: let EveryTen = ['a,'b','c'] and i need execute a function every 5 minutes for each parameters(3) inside the array.

i tried with this code but after 5 minutes run everything at once

  EveryTen.forEach(element => {
    setDelay(element)
  });


const setDelay = (element) => {
   setTimeout(function(){
     UpdateDataPost(element); //Function A
     UpdateDataBasic(element); //Function B
   }, 60 * 5 * 1000);
}

can your help me?

It is written out like this:

setInterval(function(){
     UpdateDataPost(element); //Function A
     UpdateDataBasic(element); //Function B
   }, 1000*60*5);

If you wanted to update for a different element each time, I would include some sort of counter inside of your function. Here is an example:

var i = 0;
setInterval(function(){
     UpdateDataPost(EveryTen[i]); //Function A
     UpdateDataBasic(EveryTen[i]); //Function B
     i++;
   }, 1000*60*5);

If you want to stop after each item has been used, then this would probably be the best way:

var i = 0;

var interval = setInterval(function(){
     if(i <EveryTen.length) {
       UpdateDataPost(EveryTen[i]); //Function A
       UpdateDataBasic(EveryTen[i]); //Function B
       i++;
     } else {
        clearInterval(interval);
     }
   }, 1000*60*5);

This feels like a recursive problem to me :)

Why don't you call setDelay within setInterval ? Using your example:

 EveryTen.forEach(element => {
   setDelay(element)
 });


 const setDelay = (element) => {
    setTimeout(function(){
       UpdateDataPost(element); //Function A
       UpdateDataBasic(element); //Function B
       setDelay(element);   // Added this.
    }, 60 * 5 * 1000);
 }

Or even simpler, use setInterval :

const startInterval = (element) => {
   setInterval(function(){ 
       // Do something
   }, 60 * 5 * 1000);
}

This is a good use case for setInterval , we just define the interval that it runs at (5 min) and it will add that into the event loop. Knowing that, we can take a little bit of a different approach using a counter to track the number of intervals passed, which allows us to process each bucket.

Then once the number of intervals is GTE the length of the array, we know that all of them have been processed and can clear the interval to stop it from continuing.

const everyTen = ['a', 'b', 'c'];

const updateDataPost = (data) => {
  console.log(`updateDataPost ${data}`);
};

const updateDataBasic = (data) => {
  console.log(`updateDataBasic ${data}`);
};

let intervalsPassed = 0;

const interval = setInterval(() => {
  const currentBucket = everyTen[intervalsPassed++];
  updateDataPost(currentBucket);
  updateDataBasic(currentBucket);
  if (intervalsPassed >= everyTen.length) {
    console.log('no more buckets, stopping interval')
    clearInterval(interval);
  }
}, 1000 * 60 * 5);

Output:

"updateDataPost a"
"updateDataBasic a"

"updateDataPost b"
"updateDataBasic b"

"updateDataPost c"
"updateDataBasic c"

Here is a JS bin to play around with, I set the to 5 seconds to make it quicker to test https://jsbin.com/fafewelufi/edit?js,console

With one function for all values

 var arr = ["a", "b", "c"]; function output(val) { console.log(val); } function setTimeouts(arr, ms, f) { arr.forEach(function(val, i) { setTimeout(function() { f(val); }, ms * (i + 1)); }); } // Change 3000 -> 1000 * 60 * 5 setTimeouts(arr, 3000, output); 

With a custom function for each value

 var arr = ["a", "b", "c"]; function f1(val) { console.log("This is f1 with val: " + val); } function f2(val) { console.log("This is f2 with val: " + val); } function f3(val) { console.log("This is f3 with val: " + val); } function setTimeouts(arr, ms, fns) { arr.forEach(function(val, i) { setTimeout(function() { fns[i](val); }, ms * (i + 1)); }); } // Change 3000 -> 1000 * 60 * 5 setTimeouts(arr, 3000, [f1, f2, f3]); 

I'll give you what would be my solution to this problem.

From what I gather you want to process only one element every 5 minutes, until the last is entirely processed. This is my suggestion:

const ProcessListInInterval = (interval, list, callback) => {
  // Sets a delay for the element at the `index` position
  const setDelay = (index) => {
    // Only sets the delay if index < 0
    if (index < list.length) {
      setTimeout(() => {
        const element = list[index];
        // Process element
        callback(element);

        // Sets delay for the next index, you could potentially add code
        // to reset the index here, if you don't want this to ever stop
        setDelay(time, index + 1);
      }, interval);
    }
  };

  // Start from index 0
  setDelay(0);
};

ProcessListInInterval(300000 /* 5 * 60 * 1000 */, EveryTen, (element) => {
  // Do processing here
});

This could work with setInterval too, but I like this because of three reasons:

  1. the code of ProcessListInInterval is immutable, it doesn't change your list and you can't mess around with its local variables
  2. it is isolated, there is no variables escaping the function scope
  3. it is generic and reusable

I'm also a functional programming aficionado, so I do prefer this style of immutability + recursion.

async/await makes this pretty & simple.

 function wait(ms) { return new Promise((res) => setTimeout(res, ms)); } async function main() { for (const element of EveryTen) { update(element); await wait(5 * 1000); // wait 5 seconds for example purposes } } // below not relevant specific implementation details function update(element) { UpdateDataPost(element); //Function A UpdateDataBasic(element); //Function B } function UpdateDataPost(element) { element.textContent = `updated at ${new Date()}` } function UpdateDataBasic(element) { document.querySelector(".basic").textContent = `updated at ${new Date()}` } const EveryTen = Array.from(document.querySelectorAll(".post")); main(); 
 <h2>post 1</h2> <p class="post">post not updated</p> <h2>post 2</h2> <p class="post">post not updated</p> <h2>post 3</h2> <p class="post">post not updated</p> <h2>post 4</h2> <p class="post">post not updated</p> <h2>post 5</h2> <p class="post">post not updated</p> <h2>Basic</h2> <p class="basic">basic not updated</p> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM