Here is a very nice and tiny library from Samrith Shankar Concurent Tasks
And a demo : DemoTasks
function sleep (ms) {
return new Promise((res, rej) => {
setTimeout(() => {
res(ms)
}, ms)
})
}
const task = (i) => async (done) => {
done(); // automatically added by the library
let r = await sleep(Math.random() * 500);
results.innerHTML += (`<div class="task">task${i} ended in ${r} ms</div>`);
}
function createTasks (number = 3) {
let tasks = []
for (let i = 0; i < number; i++) {
tasks.push(task(i) )
}
return tasks
}
const runner = new TaskRunner()
function start_tasks () {
results.innerHTML = "";
runner.addMultiple(createTasks());
}
Enhanced version with AI:
h1("Concurrent Test (requestAnimationFrame)")
class LineCounter {
constructor({ delay, label = "count", start = 0 }) {
this.value = start
this.label = label
this.delay = delay
this.lastTime = performance.now()
this.el = p(this.format())
}
update(now) {
if (now - this.lastTime >= this.delay) {
this.value++
this.el.textContent = this.format()
this.lastTime = now
}
}
format() {
return `${this.label} = ${this.value}`
}
}
// create counters
const counters = [
new LineCounter({ delay: 100, label: "fast" }),
new LineCounter({ delay: 650, label: "medium" }),
new LineCounter({ delay: 1550, label: "slow" })
]
// single animation loop
function loop(now) {
counters.forEach(counter => counter.update(now))
requestAnimationFrame(loop)
}
requestAnimationFrame(loop)
Fixed Time Step
h1("Concurrent Test (fixed timestep)")
class LineCounter {
constructor({ step, label = "count", start = 0 }) {
this.value = start
this.label = label
this.step = step
this.accumulator = 0
this.el = p(this.format())
}
tick() {
this.value++
this.el.textContent = this.format()
}
format() {
return `${this.label} = ${this.value}`
}
}
// counters with fixed steps (ms)
const counters = [
new LineCounter({ step: 100, label: "fast" }),
new LineCounter({ step: 650, label: "medium" }),
new LineCounter({ step: 1550, label: "slow" })
]
let lastTime = performance.now()
function loop(now) {
const delta = now - lastTime
lastTime = now
counters.forEach(counter => {
counter.accumulator += delta
while (counter.accumulator >= counter.step) {
counter.tick()
counter.accumulator -= counter.step
}
})
requestAnimationFrame(loop)
}
requestAnimationFrame(loop)
Top comments (7)
Hy,
mayby I did not get the point? This seemed already to be easy in JS...
see DEMO
Hy Eckehard,
I am building a web scrapper.
I need to query some Proxy wich limits concurents requests, that's why I ma interested in this library
Here is a demo of what I ma trying to do : WS
This is a draft, in real I use DML :)
Which kind of limitation do we face here? I know, that Javascript is single threaded, so we possibly could block the execution. But IΒ΄m not really aware about the differences in the approach you describe...
In fact the limitations is not in Javascript.
The problem is to be able to make a limited concurents requests / s
For example, my host don't permit mor than 5 request/s, and I have many requests to do.
So I have to find a way to put all requests in queue and manage the calling...
Betwise, this is a neat tip, I am trying to use for my use case... :-)
Using a fixed request rate might limit your performance. Maybe itΒ΄s better to limit the number of open request allow the next request only, if the number of open requests is lower than a certain amount. This cares to keep enough requests open, but not flooding your API. You should also care for requests that are never answered, so there should be some kind of timeout to delete unanswered requests after some time.
This kind of event handling is best done with objects, that care for their own state. You can use a simple array as a stack, new request objects are just pushed ontop of this stack. Objects that are finished should be able to remove themselves from the stack. Everytime, a request is finished, it can trigger the next waiting object on the stack.
Thank you Eckehard, great advices