Can you write this without using a Deferred?

后端 未结 2 1366
难免孤独
难免孤独 2020-12-20 03:54

I wrote some code below that uses promises and the easiest way I could find to write it was using a Deferred object instead of the usual Promise executor functi

2条回答
  •  轮回少年
    2020-12-20 04:47

    Maybe the below is just a poor man's approach to deferreds, and doesn't really get to the crux of the matter, but instead of a queue of deferreds, you could just keep a queue of resolver functions.

    This saves a small amount of code over your approach and avoids explicitly using Deferreds.

    I don't know if there is an established pattern for this, but this in itself seems like a reusable pattern for maintaining an asynchronous pool of objects, so rather than calling it WorkerList, you could name it AsyncPool, and then compose that as a reusable piece within your WorkerList:

    class AsyncPool {
        constructor() {
            this.entries = [];
            this.resolverQueue = [];
        }
        add(entry) {
            console.log(`adding ${entry}`);
            this.entries.push(entry);
    
            // if someone is waiting for an entry,
            // pull the oldest one out of the list and
            // give it to the oldest resolver that is waiting
            while (this.resolverQueue.length && this.entries .length) {
                let r = this.resolverQueue.shift();
                r(this.entries.shift());
            }
        }
        // if there's an entry, get one immediately
        // if not, return a promise that resolves with an entry
        //    when next one is available
        get() {
            return new Promise((r) => 
                this.entries.length
                    ? r(this.entries.shift())
                    : this.resolverQueue.push(r)
            );
        }
    }
    
    
    let pool = new AsyncPool();
    
    pool.add('Doc');
    pool.add('Grumpy');
    pool.get().then(console.log);
    pool.get().then(console.log);
    pool.get().then(console.log);
    pool.get().then(console.log);
    
    // add more entries later
    setTimeout(() => pool.add('Sneezy'), 1000);
    setTimeout(() => pool.add('Sleepy'), 2000);

提交回复
热议问题