Skip to content

Instantly share code, notes, and snippets.

@jooyunghan
Last active December 22, 2017 01:37
Show Gist options
  • Save jooyunghan/c04d1d9a58cd153be114b8f501c1f5b3 to your computer and use it in GitHub Desktop.
Save jooyunghan/c04d1d9a58cd153be114b8f501c1f5b3 to your computer and use it in GitHub Desktop.
Async Generator Wrapper. Can be used with normal generator functions
export function ag(f) {
const promises = [];
const g = f();
return {
[Symbol.asyncIterator]() {
return this;
},
next(input) {
if (promises.length > 0) {
return new Promise((resolve, reject) => {
promises.push({ input, resolve, reject });
});
}
try {
const { value, done } = g.next(input);
if (done) {
return Promise.resolve({ done: true });
} else if (value && typeof value.then === "function") {
value.then(this.resolve.bind(this), this.reject.bind(this));
return new Promise((resolve, reject) => {
promises.push({ resolve, reject });
});
} else {
return Promise.resolve({ done, value });
}
} catch (e) {
return Promise.reject(e);
}
},
resolve(input) {
this.step(() => g.next(input));
},
reject(err) {
this.step(() => g.throw(err));
},
step(resume) {
try {
const { value, done } = resume();
if (done) {
promises.splice(0).forEach(p => p.resolve({ done: true }));
} else if (value && typeof value.then === "function") {
value.then(this.resolve.bind(this), this.reject.bind(this));
} else {
promises.shift().resolve({ done, value });
if (promises.length > 0) {
Promise.resolve(promises[0].input).then(this.resolve.bind(this));
}
}
} catch (e) {
promises.shift().reject(e);
promises.splice(0).forEach(p => p.resolve({ done: true }));
}
},
return() {
g.return();
},
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment