I searched but failed to find a canonical pattern for ES6 promise-based queue. In fact all I am making is a step-wise FIFO buffer to ensure that messages don't collide so a very simple queue structure: like a message, sausage machine...
All it does is create a chain of promises, that resolve, at a fixed interval, to the messages in the order that they were received.
It's important for my application to know when the queue has been cleared and the only way I could think to do this was to add a Promise.all
after the last message has gone into the queue (I use a setTimeout to simulate this).
To feed the Promise.all
, I'm accumulating an array of references to the chained promises and just for the hell of it, shifting them out of the queue after they resolve.
I puzzled over how to do this without adding the array, like to somehow kick a .then(_ => console.log('done')
ahead of each new promise. In other words a queue 'head' that I unplug from the previous last element and plug into the current added promise. But I couldn't figure out how to achieve that.
Is there a better way than this?
'use strict';
var t = 500;
function write (x, enc, cb) {
process.stdout.write('write: ' + x);
cb(x-1)
}
function f(x, write) {
return new Promise(res => {
setTimeout(_ => write(x, null, res), t)
})
}
console.log('start');
var q = Promise.resolve(0);
var qs = [q];
[1,2,3,4,5,6,7,8,9,10]
.map(n => {
return {
cb: function (_) {
console.log('\tcb ' + n);
qs.shift();
return _
},
x: n
}
}) // [{ cb, x }...]
.forEach(
(o) => {
q = q.then(() =>
f(o.x, write) // return a promise to write
.then(_ => o.cb(_ + 1)) // followed by a synchronous write
);
qs.push(q);
});
// monitor queue
setTimeout(_ => {
console.log('register all ' + qs.length);
Promise.all(qs).then(a => { // detect queue completed
console.log('all done');
a.forEach((_, i) => console.log(_ + '\t' + i))
});
} , t*5);
stout
andstderr
onto the console. \$\endgroup\$