Racing promises and consuming them in the order of their resolution time The ideas are

When multiple async calls are made, to be able to start consuming from the first resolving one regardless in what order the promises are fired.
To construct a modern emitter of async values to be consumed by the for await loop.
One may achieve this functionality by making repeated (promise many times) Promise.race()s but i want to believe that no good programmer would feel comfortable with that.
Because both it's wasteful and  i never liked Promise.race(). It's a misnomer. I mean where in the world there is a race that finalizes once somebody wins? It's an insult. It's like calling the second one &quot;Hey.. you are at the top of all losers&quot;. Let's change that.

One implementation of this functionality could be starting to render a multipart entity earlier than otherwise. There might be other use cases too, since this will not reject altogether even if a promise in the system gets somehow rejected. We can easily handle rejections in an isolated manner, separatelly, perhaps for retrying or whatnot. Also the promises can be identified as they resolve and we can tell where to use their resolution.
The code below is just a skeleton.

It just shows the mechanism with a simple exception handling.
It doesn't include any retry or promise identification abilities.
It doesn't remove the consumed (fulfilled) promise from the structure. This can be iplemented in the finally block. Once it's implemented, the count variable will be redundant and we can then use the dynamic length property instead.
Being able to use the dynamic length property would allow us to add, remove or replace promises at any point in time just by using standard array methods like .push() or .splice() etc.
It uses the new Private Class Fields which i like a lot.

We will start with a new data type called SortedPromisesArray which in fact is an extension to the Array type. We will empower it with generator and asyncIterator abilities.
export default class SortedPromisesArray extends Array {
  #resolve;
  #reject;
  #count;
  constructor(...args){
    super(...args.filter(p =&gt; Object(p).constructor === Promise)); // Make sure everybody is a Promise
    this.#count = this.length;
    this.forEach(p =&gt; p.then(v =&gt; this.#resolve(v), e =&gt; this.#reject(e)));
  };
  async *[Symbol.asyncIterator]() {
    while(this.#count--) {
      try {
        yield new Promise((...rs) =&gt; [this.#resolve,this.#reject] = rs);
      }
      catch(e){
        console.log(`Caught an exception ${e}`);
      }
      finally{
        // a handy stage to do useful things
      };
    };
  };
};

and we can consume it like;
import SPA from &quot;../lib/promise-sort.js&quot;;

var promise  = (val,delay,isOK) =&gt; new Promise((v,x) =&gt; setTimeout(_ =&gt; isOK ? v(val) : x(val), delay)),
    promises = [ promise(&quot;Third&quot;, 3000, true)
               , promise(&quot;First&quot;, 1000, true)
               , Promise.resolve(&quot;this is solved first @ microtask queue&quot;)
               , promise(&quot;Second&quot;, 2000, false) // NOTE: this one rejects!
               ],
    sortedPS = new SPA(...promises);

async function sink() {
  for await (let value of sortedPS){
      console.log(`Got: ${value}`);
  };
};

sink();

Any thoughts and recommendations are most welcome.
Issues
Lost resolution
You are issuing promises without a guarantee of being able to handle all or some of the resolving promises.
This will happen if promises resolve before you start the for await loop.
The offending code is in the line this.forEach(p =&gt; p.then(v =&gt; this.#resolve(v), e =&gt; this.#reject(e)));
The calls to this.#resolve and this.#reject require that the asyncIterator is run so that this.#resolve and this.#reject are assigned functions. If not they are undefined when a promise resolves.
It is also possible for a promise to overwrite the previous promise's resolved value without the iterator getting to see the value.
For example:

if you delay the call to sink(); with setTimeout(sink, 4000) none of the promises are handled within the function sink. The results are lost and can not be retrieved

If the iterator awaits content that allows more than one of the iterateable promises to resolve between iterations.
Example the following function loses the second promise. (given your test data)


async function sink() {
    const p = new Promise(v=&gt;setTimeout(v, 1200, &quot;zz&quot;))
    for await (const value of sortedPS){
       log(value);
       log(await p);
    };
};

Silencing errors!
Never silence errors that are not your responsibility.
You do this in the line:
super(...args.filter(p =&gt; Object(p).constructor === Promise)); // Make sure everybody is a Promise

Either throw an error or let the error happen naturally. If your code can not function correctly with the given arguments then throw
Example of vetting and throwing error:
constructor(...promises){
    super(...promises);
    if (promises.some(promise =&gt; !(promise instanceof Promise))) {
        throw new RangeError(&quot;Array can only contain Promises&quot;);
    }

Poor inheritance
You extend Array yet neglect to handle any of the inherited functions or properties.
For example one would expect that SortedPromisesArray.push would add a promise that will resolve. As it stands added promises are ignored.
Simple example of extending inherited function:
  push(...promises) {
      if (promises.some(promise =&gt; !(promise instanceof Promise))) {
          throw new RangeError(&quot;Array can only contain Promises&quot;);
      }      
      this.#count += promises.length;
      super.push(...promises);
      promises.forEach(p =&gt; p.then(v =&gt; this.#resolve(v), e =&gt; this.#reject(e)));
  }

The same would apply to any of the inherited functions that modify the arrays content.
Arrays are independent of content
However this leaves the problem of behaviors that can not be extended without the use of a proxy. Eg sortedPS[sortedPS.length] = new Promise(...)
Without a proxy you are left with an object that has inconsistent behavior.
It is therefor not advisable to extend Arrays if behavior of the extended array is dependent on the content of the array.
Update
I have added an example RaceAll as a factory that creates an async iterate-able object that races an array of promises in order of resolution.
This is achieved by marking promises with ids and using the id of resolved promises to remove then from the race array.
It does not include any vetting, nor does it resolve rejected / failed promises (both can easily be implemented).
It does guarantee no promises are lost and does not require iteration before any promises are resolved.
function RaceAll(...promises) {
    var racing = promises.map((promise, id) =&gt; Object.assign(
            new Promise(r =&gt; promise.then(result =&gt; r({id, result}))), {id}
        ));
    return Object.freeze({
            async *[Symbol.asyncIterator]() {
                while (racing.length) {
                    const resolved = await Promise.race(racing);
                    yield resolved.result;
                    racing = racing.filter(r =&gt; r.id !== resolved.id);
                }
            }
        });
}