-
Notifications
You must be signed in to change notification settings - Fork 136
Description
I realized today that some utility scripts I wrote are no longer working since the current version explicitly checks for and throws on defer after await. Reviewing when/why this might have gotten enforced it looks like I have a history of beating this drum already!
My use case boils down to essentially cases of "pagination" or "following linked lists asyncronously". I.e. the task I'm enqueuing does some work and only in the process of doing said work determines whether more work needs to be done. Thus my pattern is to create a queue, defer the initial task, and immediately awaitAll the eventual results.
My current workaround is to hack around the assertion:
const {queue:q} = require('d3-queue');
const _actualDefer = q.prototype.defer;
q.prototype.defer = function () {
var _origCall = this._call;
this._call = null;
var result = _actualDefer.apply(this, arguments);
this._call = _origCall;
return result;
};
My proposal would be that defer can be called at any time before the notification actually happens. Likely implementation would be something like:
const TOMBSTONE = Symbol("await called"); // NOTE: `Object.create(null);` for older JS engines would suffice
function maybeNotify(q) {
if (!q._active && q._call) {
var d = q._data;
q._data = undefined; // allow gc
q._call(q._error, d);
q._call = TOMBSTONE;
}
}
and replacing
if (this._call) throw new Error("defer after await");
with
if (this._call === TOMBSTONE) throw new Error("defer after await called");`
I can submit a PR including any ancillary doc/test changes if you'd be amenable to this behavior change.