Detect the last resolve in an ES6 promise chain 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(_ =&gt; 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 =&gt; {
    setTimeout(_ =&gt; 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 =&gt;  {
    return {
      cb: function (_) {
        console.log('\tcb ' + n);
        qs.shift();
        return _
      },
      x: n
    }
  })  // [{ cb, x }...]
  .forEach(
    (o) =&gt; {

      q = q.then(() =&gt;
        f(o.x, write)   // return a promise to write
          .then(_ =&gt; o.cb(_ + 1)) // followed by a synchronous write
      );
      qs.push(q);

    });

// monitor queue
setTimeout(_ =&gt; {
  console.log('register all ' + qs.length);
  Promise.all(qs).then(a =&gt; {   // detect queue completed
    console.log('all done');
    a.forEach((_, i) =&gt; console.log(_ + '\t' + i))
  });
} , t*5);
Code in the question is hard to follow but it would appear that you are struggling to do something that's achieved very simply with this pattern, with which detection of "the last resolve in an ES6 promise chain" falls out in the wash. Read and understand that before continuing below.

If I'm correct, then you could write :

function makeAsyncSequence(arr, callback) {
    return arr.reduce((chain, item) =&gt; {
        return chain.then(() =&gt; callback(item));
    }, Promise.resolve());
}


And you would call :

makeAsyncSequence([1,2,3,4,5], doSomethingAsync).then(finalResult =&gt; {
    console.log('complete');
});


This is so simple that, in practice, we would normally choose to write arr.reduce(...) out longhand in our application everywhere it's needed. A special utility function like above is seldom needed.

Now, if you wish to impose a minimum delay that is not already imposed by the callback function :

First a delay function ...

function delay(t) {
    return new Promise(resolve =&gt; setTimeout(resolve, t));
};


... and an enhanced version of makeAsyncSequence(), in which callback(item) is aggregated with delay(minimumDelay) :

function makeAsyncSequence(arr, callback, minimumDelay) {
    minimumDelay = +minimumDelay || 0;
    return arr.reduce((chain, item) =&gt; {
        return chain.then(() =&gt; {
            if (minimumDelay) {
                return Promise.all([callback(item), delay(minimumDelay)]); // the slower of the two async processes determines the timing of the returned promise's success path.
            } else {
                return callback(item); // no minimumDelay required, therefore act as in the simple case.
            }
        });
    }, Promise.resolve());
}


And you would call :

makeAsyncSequence([1,2,3,4,5], doSomethingAsync, 1000).then(finalResult =&gt; {
    console.log('complete');
});


demo

Due to the increased complexity we would probably choose to write this as above in our application - ie as pair of special utilities.