Skip to content

PubSub iterator promise never resolves if return() called too soon #201

Open
@arendjr

Description

@arendjr

The following snippet will result in an iterator promise returned by next() that never resolves:

const iterator = new PubSub().asyncIterator();
const promise = iterator.next();
iterator.return();
await promise; // will wait forever

The trick is that return() gets called synchronously while the first call to next() is still setting up its subscriptions.

This appears to be a regression since 1.0 since I have a test suite that was green and started failing on this issue when I upgraded to 1.1.

I have tried various solutions, including monkey-patching emptyQueue() like this:

PubSubAsyncIterator.prototype.emptyQueue = async function() {
    if (this.running) {
        this.running = false;
        this.pullQueue.forEach(resolve => resolve({ value: undefined, done: true }));
        this.pullQueue.length = 0;
        this.pushQueue.length = 0;
        const subscriptionIds = await this.allSubscribed;
        if (subscriptionIds) {
            this.unsubscribeAll(subscriptionIds);
        }
        // This one should make sure new next() calls while we were awaiting and resolved:
        this.pullQueue.forEach(resolve => resolve({ value: undefined, done: true }));
    }
};

But interestingly, doing so made other tests in my suite fail for reasons I'm afraid I don't understand right now... Ignore this last part, that failure seemed to be caused by me mis-using Jest's .resolves method (forgetting to await it).

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions