You can just use an array.
Note that my code's output is slightly different from yours—I don't get "v 14". I'm not sure why you expect that output... you're queueing up four function calls but expect five lines of output?
const q = [];
let v = 0;
function fun (arg) {
console.log('v', v);
setTimeout(() => {
v = v + arg;
var next = q.shift();
if (next) { next(); }
});
}
q.push(() => { fun(2); });
q.push(() => { fun(3); });
q.push(() => { fun(4); });
q.push(() => { fun(5); });
q.shift()(); // run the first one
// OUTPUT:
// v 0
// v 2
// v 5
// v 9
EDIT
Here's perhaps a better version that has the added advantage that it will work properly no matter when things are enqueued. In the above code, you have to manually start running things, and once the queue is exhausted, nothing later added will ever be run. In the below FunctionQueue class, execution happens automatically whenever there's at least one function to run:
class FunctionQueue {
constructor() {
this.queue = [];
this.running = false;
}
go() {
if (this.queue.length) {
this.running = true;
this.queue.shift()(() => { this.go(); });
} else {
this.running = false;
}
}
add(func) {
this.queue.push(func);
if(!this.running) {
this.go();
}
}
}
let v = 0;
function fun (arg, cb) {
console.log('v', v);
v += arg;
setTimeout(cb, 100);
}
const q = new FunctionQueue();
// Execution will automatically start once something is enqueued.
q.add((cb) => { fun(2, cb); });
q.add((cb) => { fun(3, cb); });
q.add((cb) => { fun(4, cb); });
q.add((cb) => { fun(5, cb); });
// At this point, nothing's running anymore.
// Enqueueing something much later will resume execution again.
setTimeout(() => {
q.add((cb) => { fun(6, cb); });
}, 1000);
// OUTPUT:
// v 0
// v 2
// v 5
// v 9
// v 15
fun()doesn't return anything, what are you expecting to put in the queue?q.add()supposed to be a function to call? You're not passing a function, you're calling the function and passing its value toq.add().