async/awaitをジェネレータで実装してみる
JavaScriptのasync/awaitはコルーチンという仕組みによって実装されている。
コルーチンはジェネレータによっても使えるため、擬似的にasync関数を実装してみる。
code:js
function async(gen) {
return function () {
const iter = gen.apply(this, arguments);
return new Promise((fulfill, reject) => {
const next = (result) => {
const { value, done } = iter.next();
if (done) {
fulfill(value);
} else {
if (value instanceof Promise) {
value.then(next, reject);
} else {
next(value);
}
}
};
next(undefined);
});
};
}
このようにasync関数を定義する。
使い方:
asyncな関数を定義したいときは、asyncFunc = async(function *() { ... });とする。
awaitしたいときは、代わりにyieldキーワードを使用する。
比較:
code:js
async function getTwoDataAndCombine() {
fetch("data1.txt").then(res => res.text()),
fetch("data2.txt").then(res => res.text()),
]);
return data1 + "\n" + data2;
}
async function sleepAndPrint(time, text) {
await new Promise(done => setTimeout(done, time));
console.log(text);
}
code:js
const getTwoDataAndCombine = async(function *() {
fetch("data1.txt").then(res => res.text()),
fetch("data2.txt").then(res => res.text()),
]);
return data1 + "\n" + data2;
});
const sleepAndPrint = async(function *(time, text) {
yield new Promise(done => setTimeout(done, time));
console.log(text);
});
なお、このasync関数によって定義された関数は、async/awaitキーワードによって定義された関数と互換性がある。