Reputation: 1828
I have a scenario where I need to schedule multiple timeouts in vanilla JS, it will be something like this below:
const scheduler = {
done: function() {},
schedule: function() {}
};
scheduler.schedule(function(done) {
setTimeout(() => {
console.log(1);
done()
}, 2000);
});
scheduler.schedule(function(done) {
setTimeout(() => {
console.log(2);
done()
}, 1000);
});
scheduler.schedule(function(done) {
setTimeout(() => {
console.log(3);
done()
}, 3000);
});
it should execute it in such a way that it must print below:
1
2
3
Upvotes: 3
Views: 485
Reputation: 18619
This is a nice use case of promises.
These objects allow the abstraction over asynchronous operations, and fortunately, can be chained.
const scheduler = {
last: Promise.resolve(),
schedule(cb){
this.last = this.last.then(() => new Promise(cb))
}
}
scheduler.schedule(function(done) {
setTimeout(() => {
console.log(1);
done()
}, 2000);
});
scheduler.schedule(function(done) {
setTimeout(() => {
console.log(2);
done()
}, 1000);
});
scheduler.schedule(function(done) {
setTimeout(() => {
console.log(3);
done()
}, 3000);
});
However, if you use this with promises you obtained from elsewhere , it can quickly turn into the Explicit Promise construction antipattern, so, for a more general code, move the new Promise()
part out of the schedule
method:
const scheduler = {
last: Promise.resolve(),
schedule(cb){
this.last = this.last.then(cb)
}
}
scheduler.schedule(function() {
return new Promise(done => {
setTimeout(() => {
console.log(1);
done()
}, 2000);
})
});
scheduler.schedule(function() {
return new Promise(done => {
setTimeout(() => {
console.log(2);
done()
}, 1000);
})
});
scheduler.schedule(function() {
return new Promise(done => {
setTimeout(() => {
console.log(3);
done()
}, 3000);
})
});
Upvotes: 3
Reputation: 4912
const scheduler = {
done: function (cb) {
cb();
this.timeouts.shift();
this.timeouts[0] && this.timeouts[0]();
},
schedule: function (cb, ms) {
const timeout = () => setTimeout(this.done.bind(this), ms, cb);
this.timeouts.push(timeout) == 1 && timeout();
},
timeouts: [],
};
scheduler.schedule(() => console.log('1'), 2000);
scheduler.schedule(() => console.log('2'), 1000);
scheduler.schedule(() => console.log('3'), 3000);
Upvotes: -1
Reputation: 2812
You would need a que for the timeouts, eg:
const scheduler = {
done:function(){}, // Not sure what this function is supposed to do
schedule:function(callback, timeout) {
scheduler.que.push([callback, timeout]); // Add the function along with its wait time
if(scheduler.que.length == 1) scheduler.startQue(); // If the que was previously empty, start the execution of the que
},
startQue() {
setTimeout(() => {
scheduler.que[0][0](); // run the callback timeout
scheduler.que.shift(); // Remove the just ran timeout
if(scheduler.que.length >= 1) scheduler.startQue(); // Start another timeout if we still have some in the que
}, scheduler.que[0][1]);
},
que: []
};
scheduler.schedule(() => console.log(1), 2000); // Wait for 2 seconds to print
scheduler.schedule(() => console.log(2), 1000); // Wait 1 second after the first one printed
scheduler.schedule(() => console.log(3), 3000); // Wait another 3 seconds after the second one
Upvotes: 1