I need to trigger up to 12 "events" with timings a user sets. The
timings (in seconds) could be anything from 0 to, say, 300.
One way I though to handle them was to: put the timings into an array,
sort the array (from lowest to highest), loop over the array and call setTimeout on each one.
Andrew Poulos <ap_prog@hotmail.com> writes:
I need to trigger up to 12 "events" with timings a user sets. The
timings (in seconds) could be anything from 0 to, say, 300.
One way I though to handle them was to: put the timings into an array,
sort the array (from lowest to highest), loop over the array and call
setTimeout on each one.
Hmm... Why not just call setTimeout without sorting them? I must be
missing some key part of the problem...
On 17/06/2021 11:06 am, Ben Bacarisse wrote:
Andrew Poulos <ap_prog@hotmail.com> writes:
I need to trigger up to 12 "events" with timings a user sets. TheHmm... Why not just call setTimeout without sorting them? I must be
timings (in seconds) could be anything from 0 to, say, 300.
One way I though to handle them was to: put the timings into an array,
sort the array (from lowest to highest), loop over the array and call
setTimeout on each one.
missing some key part of the problem...
If I have 12 setTimeout waiting to happen and the user gives focus to
a different "component" I'll need to clear all the setTimeout.
(response from Ben Bacarisse elided)
Andrew Poulos wrote:
I need to trigger up to 12 "events" with timings a user sets. The
timings (in seconds) could be anything from 0 to, say, 300.
If I have 12 setTimeout waiting to happen and the user gives focus to a different "component" I'll need to clear all the setTimeout. I was
looking for a single point to control all of them without multiple setTimeout.
At some later stage the client might ask for "unlimited" timings and I'd rather not have lots of setTimeout running at the same time.
Andrew Poulos wrote:
(response from Ben Bacarisse elided)
Andrew Poulos wrote:
I need to trigger up to 12 "events" with timings a user sets. The
timings (in seconds) could be anything from 0 to, say, 300.
If I have 12 setTimeout waiting to happen and the user gives focus to a
different "component" I'll need to clear all the setTimeout. I was
looking for a single point to control all of them without multiple
setTimeout.
At some later stage the client might ask for "unlimited" timings and I'd
rather not have lots of setTimeout running at the same time.
Dozens, hundreds, probably even thousands of `setTimeout` calls will
probably not slow down modern browsers. But it would feel ... uncleanly.
It would be easy enough to run a single `getInterval` timer that when it
runs checks the remaining actions and runs all those whose time is at hand. You would need to choose a run-time interval short enough to capture the likely timing differences between your events but long enough not to clog
up the event queue. For events measured in seconds, up to 300, I would
think running every 250 milliseconds might be reasonable.
Here's an implementation:
```
const handler = (periodInMilliseconds) => (events) => {
const start = Date .now ()
let toProcess = events .map (
([fn, delayInSecs]) => ({fn, runTime: start + 1000 * delayInSecs})
)
const interval = setInterval (
() => {
const now = Date .now ()
toProcess .filter (e => e .runTime <= now) .forEach (e => e .fn ())
toProcess = toProcess .filter (e => e .runTime > now)
},
periodInMilliseconds
)
return {
stop: (after = () => {}) => {clearInterval (interval); after ()}
}
}
```
which might be used like this:
```
const {stop} = handler (250) ([
[() => console .log ('A'), 4],
[() => console .log ('B'), 2],
[() => console .log ('C'), 15],
[() => console .log ('D'), 7],
[() => console .log ('E'), 1],
])
setTimeout (() => stop (() => console.log ('completed')), 10000)
```
You call handler passing the period (250ms) and an array of arrays,
each containing a function to run and the delay in seconds. You get
back a `stop` function which will terminate the running (and call
an optional callback afterward if you like.)
At the start, the functions are paired with the time they should run.
At each interval, we calculate the current time and, if checks each
function. If it is now due, we run the function and remove it from
the `toProcess` list.
The example above would log `E` after one second, `B` after two
seconds, `A` after four seconds, `D` after seven seconds. But
because we call `stop` after ten seconds, the events are stopped
before we reach `C`. Note that our optional callback will log
`completed` at that time.
This is a fairly naive version. We might want to improve it to clear
the interval when the queue is empty. We might want to add an explicit `start` parallel to `stop`, to start the queue when we choose. Or we
might want to specify the `stop` callback initially with the period.
And many other improvements are certainly possible. But it's a decent
start at the problem.
fredag 18 juni 2021 kl. 03:04:02 UTC+2 skrev Andrew Poulos:
On 18/06/2021 6:21 am, Scott Sauyet wrote:
Andrew Poulos wrote:
(response from Ben Bacarisse elided)
Andrew Poulos wrote:
I need to trigger up to 12 "events" with timings a user sets. The >>>> timings (in seconds) could be anything from 0 to, say, 300.
If I have 12 setTimeout waiting to happen and the user gives focus to a >> different "component" I'll need to clear all the setTimeout. I was
looking for a single point to control all of them without multiple
setTimeout.
At some later stage the client might ask for "unlimited" timings and I'd
rather not have lots of setTimeout running at the same time.
Dozens, hundreds, probably even thousands of `setTimeout` calls will probably not slow down modern browsers. But it would feel ... uncleanly.
It would be easy enough to run a single `getInterval` timer that when it runs checks the remaining actions and runs all those whose time is at hand.
You would need to choose a run-time interval short enough to capture the likely timing differences between your events but long enough not to clog
up the event queue. For events measured in seconds, up to 300, I would think running every 250 milliseconds might be reasonable.
Here's an implementation:
```
const handler = (periodInMilliseconds) => (events) => {
const start = Date .now ()
let toProcess = events .map (
([fn, delayInSecs]) => ({fn, runTime: start + 1000 * delayInSecs})
)
const interval = setInterval (
() => {
const now = Date .now ()
toProcess .filter (e => e .runTime <= now) .forEach (e => e .fn ()) toProcess = toProcess .filter (e => e .runTime > now)
},
periodInMilliseconds
)
return {
stop: (after = () => {}) => {clearInterval (interval); after ()}
}
}
```
which might be used like this:
```
const {stop} = handler (250) ([
[() => console .log ('A'), 4],
[() => console .log ('B'), 2],
[() => console .log ('C'), 15],
[() => console .log ('D'), 7],
[() => console .log ('E'), 1],
])
setTimeout (() => stop (() => console.log ('completed')), 10000)
```
You call handler passing the period (250ms) and an array of arrays,
each containing a function to run and the delay in seconds. You get
back a `stop` function which will terminate the running (and call
an optional callback afterward if you like.)
At the start, the functions are paired with the time they should run.
At each interval, we calculate the current time and, if checks each function. If it is now due, we run the function and remove it from
the `toProcess` list.
The example above would log `E` after one second, `B` after two
seconds, `A` after four seconds, `D` after seven seconds. But
because we call `stop` after ten seconds, the events are stopped
before we reach `C`. Note that our optional callback will log `completed` at that time.
This is a fairly naive version. We might want to improve it to clearThanks. It's given me something I can work with.
the interval when the queue is empty. We might want to add an explicit `start` parallel to `stop`, to start the queue when we choose. Or we might want to specify the `stop` callback initially with the period.
And many other improvements are certainly possible. But it's a decent start at the problem.
Andrew PoulosHere is how i shedule timed events.
function startIT(){
playPos=0;
stopRec=setInterval(doIT,5);
}
function doIT(){
//Play end is set in scrollbar
REALTIME=performance.now()-browserLoadTIME;
while(REALTIME>schedTime){
//Do something
schedTime=copyEv[playPos]+schedTime;
playPos++;
}
}
On 18/06/2021 6:21 am, Scott Sauyet wrote:
Andrew Poulos wrote:
(response from Ben Bacarisse elided)
Andrew Poulos wrote:
I need to trigger up to 12 "events" with timings a user sets. The
timings (in seconds) could be anything from 0 to, say, 300.
If I have 12 setTimeout waiting to happen and the user gives focus to a
different "component" I'll need to clear all the setTimeout. I was
looking for a single point to control all of them without multiple
setTimeout.
At some later stage the client might ask for "unlimited" timings and I'd >> rather not have lots of setTimeout running at the same time.
Dozens, hundreds, probably even thousands of `setTimeout` calls will probably not slow down modern browsers. But it would feel ... uncleanly.
It would be easy enough to run a single `getInterval` timer that when it runs checks the remaining actions and runs all those whose time is at hand. You would need to choose a run-time interval short enough to capture the likely timing differences between your events but long enough not to clog up the event queue. For events measured in seconds, up to 300, I would think running every 250 milliseconds might be reasonable.
Here's an implementation:
```
const handler = (periodInMilliseconds) => (events) => {
const start = Date .now ()
let toProcess = events .map (
([fn, delayInSecs]) => ({fn, runTime: start + 1000 * delayInSecs})
)
const interval = setInterval (
() => {
const now = Date .now ()
toProcess .filter (e => e .runTime <= now) .forEach (e => e .fn ()) toProcess = toProcess .filter (e => e .runTime > now)
},
periodInMilliseconds
)
return {
stop: (after = () => {}) => {clearInterval (interval); after ()}
}
}
```
which might be used like this:
```
const {stop} = handler (250) ([
[() => console .log ('A'), 4],
[() => console .log ('B'), 2],
[() => console .log ('C'), 15],
[() => console .log ('D'), 7],
[() => console .log ('E'), 1],
])
setTimeout (() => stop (() => console.log ('completed')), 10000)
```
You call handler passing the period (250ms) and an array of arrays,
each containing a function to run and the delay in seconds. You get
back a `stop` function which will terminate the running (and call
an optional callback afterward if you like.)
At the start, the functions are paired with the time they should run.
At each interval, we calculate the current time and, if checks each function. If it is now due, we run the function and remove it from
the `toProcess` list.
The example above would log `E` after one second, `B` after two
seconds, `A` after four seconds, `D` after seven seconds. But
because we call `stop` after ten seconds, the events are stopped
before we reach `C`. Note that our optional callback will log
`completed` at that time.
This is a fairly naive version. We might want to improve it to clearThanks. It's given me something I can work with.
the interval when the queue is empty. We might want to add an explicit `start` parallel to `stop`, to start the queue when we choose. Or we
might want to specify the `stop` callback initially with the period.
And many other improvements are certainly possible. But it's a decent
start at the problem.
Andrew Poulos
måndag 21 juni 2021 kl. 08:40:37 UTC+2 skrev Jonas Thörnvall:
fredag 18 juni 2021 kl. 03:04:02 UTC+2 skrev Andrew Poulos:
On 18/06/2021 6:21 am, Scott Sauyet wrote:
Andrew Poulos wrote:
(response from Ben Bacarisse elided)
Andrew Poulos wrote:
I need to trigger up to 12 "events" with timings a user sets. The >>>> timings (in seconds) could be anything from 0 to, say, 300.
If I have 12 setTimeout waiting to happen and the user gives focus to a
different "component" I'll need to clear all the setTimeout. I was
looking for a single point to control all of them without multiple
setTimeout.
At some later stage the client might ask for "unlimited" timings and I'd
rather not have lots of setTimeout running at the same time.
Dozens, hundreds, probably even thousands of `setTimeout` calls will probably not slow down modern browsers. But it would feel ... uncleanly.
It would be easy enough to run a single `getInterval` timer that when it
runs checks the remaining actions and runs all those whose time is at hand.
You would need to choose a run-time interval short enough to capture the
likely timing differences between your events but long enough not to clog
up the event queue. For events measured in seconds, up to 300, I would think running every 250 milliseconds might be reasonable.
Here's an implementation:
```
const handler = (periodInMilliseconds) => (events) => {
const start = Date .now ()
let toProcess = events .map (
([fn, delayInSecs]) => ({fn, runTime: start + 1000 * delayInSecs})
)
const interval = setInterval (
() => {
const now = Date .now ()
toProcess .filter (e => e .runTime <= now) .forEach (e => e .fn ()) toProcess = toProcess .filter (e => e .runTime > now)
},
periodInMilliseconds
)
return {
stop: (after = () => {}) => {clearInterval (interval); after ()}
}
}
```
which might be used like this:
```
const {stop} = handler (250) ([
[() => console .log ('A'), 4],
[() => console .log ('B'), 2],
[() => console .log ('C'), 15],
[() => console .log ('D'), 7],
[() => console .log ('E'), 1],
])
setTimeout (() => stop (() => console.log ('completed')), 10000)
```
You call handler passing the period (250ms) and an array of arrays, each containing a function to run and the delay in seconds. You get back a `stop` function which will terminate the running (and call
an optional callback afterward if you like.)
At the start, the functions are paired with the time they should run.
At each interval, we calculate the current time and, if checks each function. If it is now due, we run the function and remove it from
the `toProcess` list.
The example above would log `E` after one second, `B` after two seconds, `A` after four seconds, `D` after seven seconds. But
because we call `stop` after ten seconds, the events are stopped before we reach `C`. Note that our optional callback will log `completed` at that time.
This is a fairly naive version. We might want to improve it to clear the interval when the queue is empty. We might want to add an explicit `start` parallel to `stop`, to start the queue when we choose. Or we might want to specify the `stop` callback initially with the period. And many other improvements are certainly possible. But it's a decent start at the problem.Thanks. It's given me something I can work with.
Andrew PoulosHere is how i shedule timed events.
Well you should init with.function startIT(){
playPos=0;
stopRec=setInterval(doIT,5);
}
function doIT(){As you can see my timings rest in copyEV and are relative copyEV timings.
//Play end is set in scrollbar
REALTIME=performance.now()-browserLoadTIME;
while(REALTIME>schedTime){
//Do something
schedTime=copyEv[playPos]+schedTime;
playPos++;
}
}
If the copyEV timings are relative zero.....
Then you of course have some event performed at do something....
function startIT(){
playPos=0;
stopRec=setInterval(doIT,5);
}
function doIT(){
//Play end is set in scrollbar
REALTIME=performance.now()-browserLoadTIME;
while(REALTIME>schedTime){
//Do something
schedTime=copyEv[playPos];
playPos++;
}
}
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 249 |
Nodes: | 16 (2 / 14) |
Uptime: | 73:44:02 |
Calls: | 5,505 |
Files: | 11,668 |
Messages: | 5,074,987 |