Understanding javascript promise used with setTime

2019-02-15 23:08发布

问题:

Can someone help me understand these 2 lines of code and improve them to actually allow me to stop the repeats?

var wait = ms => new Promise(r => setTimeout(r, ms));
var repeat = (ms, func) => new Promise(r => (setInterval(func, ms), wait(ms).then(r)));

repeat(1000, () => Promise.all([myfunction()])
  .then(...)

回答1:

The first line (wait) simply waits a certain number of milliseconds and then ends.

The second line (repeat) programs a function to be run in a certain interval of time (setInterval), and then calls wait and passes the number of milliseconds set on repeat function to it. These function are called only once. Javascript's internal controls for setInterval is what takes control from now on calling () => Promise.all([myfunction()]) at the programmed time interval.

If you just ident your code things get clearer.

var wait = 
    ms => new Promise(
        r => setTimeout(r, ms)
    );

var repeat = 
    (ms, func) => new Promise(
        r => (
            setInterval(func, ms), 
            wait(ms).then(r)
        )
    );

repeat(1000, () => Promise.all([myfunction()]))
.then(...);

In order to stop the function you have to capture the interval's id and call clearInterval as SimpleJ pointed out. You probably will want to do this with Promises once you're all into it. So a complete working example would be:

var intervalID = 0;

var wait = 
    ms => new Promise(
        r => setTimeout(r, ms)
    );

var repeat = 
    (ms, func) => new Promise(
        r => (
            intervalID = setInterval(func, ms), 
            wait(ms).then(r)
        )
    );

var myfunction = 
    () => new Promise(
        r => r(console.log('repeating...'))
    );

var stopAfter5Secs = 
    () => new Promise(
        r => r(setTimeout(() => { 
                    clearInterval(intervalID);
                    console.log('repeat end') 
               } , 5000))
    );

repeat(1000, () => Promise.all([myfunction()])) // 1000 miliseconds = 1 second
.then(stopAfter5Secs())  // starts timer to end repetitions
.then(console.log('repeat start')); // informs that all actions were started correctly and we are waiting for them to finish

Promiss.all calls all promisses in any interable object passed to it. In this case an array with only one element (myfunction). I created a simple function which only writes 'repeating' to the console, to be that function. But you can pass any number of functions you want to it if all of them return promisses.

You can see it working here: https://jsfiddle.net/9n2knxdg/7/



回答2:

You could resolve the interval returned from setInterval once wait finishes in repeat and clear the interval with clearInterval:

var wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

var repeat = (ms, func) => new Promise((resolve) => {
  const interval = setInterval(func, ms);
  wait(ms).then(() => resolve(interval));
});

repeat(1000, () => console.log("Repeated"))
  .then((interval) => {
    console.log("Stopping repeat");
    clearInterval(interval);
  });

Although I'm not sure I understand the purpose of the repeat function.