I want to convert the Promise array into an async generator that will resolve it in the earliest order.

Asked 2 years ago, Updated 2 years ago, 109 views

Now, when there is an array of Promise, I would like to wait in the order of the resolve. ES2021 introduced the syntax for wait of, so if you have a function such as a library that converts Promise arrays into async generator that can resolve them quickly, you can do what you want.

// Example
constpromiseArray:Promise<any>[]=createPromises()

for wait (constval of promiseArray2generator(promiseArray)) {
  console.log(val)
  // processing with val
}

Converting Promise arrays into async generator is a function that I would like to have implemented as a library.If that's the case, I think it's possible that this function can be realized in famous libraries. (I don't really want to reinvent the wheel)

So I would like to ask you a question, are there any regular idioms that enable this Promise array to be converted to async generator or a library (function) that enables this?

javascript typescript promise

2022-09-30 20:19

1 Answers

There seems to be no direct idiom at the moment.

Normal (not asynchronous) iterations are often sufficient

For example, a normal for that is not forwait can do much the same as the question code.

for(const of promiseArray){
    p.then(async(val)=>{
        console.log(`val="${val}"`)
        // processing with val
    })
}

If you want to wait the whole thing, map might be better.

wait Promise.all(
    promoteArray.map(async(p)=>{
        const val = wait p
        console.log(`val="${val}"`)
        // processing with val
    }),
)

These iterations themselves are synchronous and treat Promise arrays as they are.However, the callback function registered during the iteration is called by Promise when it is ready, so it is generally the purpose of the question.

We assume that these are sufficient, or that these are often better, and therefore no asynchronous generator idioms are created.

The difference between the above repeated code and the question code (for wait + asynchronous generator)

I wrote that the code by repeating above is roughly the same as the code in the question, and I think the shape is similar.However, there are also differences.This is when await is performed in the //val Processing Various section.

  • In the above repeated code, each callback runs asynchronously:
    wait is written within each callback function.The execution of the callback function is then plotted, but each callback function is called independently, so the processing proceeds asynchronously, such as moving other callback functions while one callback function is wait.
  • In the question code, each loop proceeds sequentially:
    wait is written in the for wait loop.The loop is then blocked and does not proceed to the next element until the asynchronous wait process is resolved.

It depends on the situation, but you may misunderstand that it is the opposite at first glance, so be careful.

To achieve the code of the question (for wait + asynchronous generator)

If you can't find an idiom, but you don't want to write it from scratch, you need some foundation.As a foundation, I think a queue that allows you to take in and out values asynchronously is better.

For example, if you have AsyncSimpleQueue that allows you to add ( enqueue) and withdraw ( dequeue), you can write as follows:

async function*promiseArrayToGenerator<T>(promiseArray:Promise<T>[]){
    const queue = new AsyncSimpleQueue <T>()

    for (const of promiseArray) {
        p.then(val:T)=>{
            queue.enqueue(val)
        })
    }

    for (leti=0;i<promiseArray.length;i++){
        yield wait queue.dequeue()
    }
}

How to write an asynchronous queue

Asynchronous queues have a lot of uses, so there should be libraries.However, when you search for it, only the task queue that manages asynchronous tasks appears.So I'll give you a minimal implementation.

class AsyncSimpleQueue<T>{
    # valQueue: T[ ] = [ ]
    # resolverQueue:(val:T)=>void)[]=[]

    enqueue(val:T): void {
        const resolver=this.#resolverQueue.shift()
        if(resolver){
            resolver(val)
        } else{
            This.#valQueue.push(val)
        }
    }

    queue():Promise <T>{
        if(this.#valQueue.length>0){
            return Promise.resolve (this.#valQueue.shift()!)
        }
        return new Promise <T>(resolve)=>{
            This.#resolverQueue.push(resolve)
        })
    }
}

The code above is based on the 13.4.4 Asynchronous iterator Implementation in the book JavaScript 7th Edition.The AsyncQueue introduced there is itself an asynchronous iterator, and it also has the ability to close the queue.The author of the book reportedly referred to Dr. Rauschmayer's blog.


2022-09-30 20:19

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.