Designing type-safe sync/async mode support in TypeScript
11 points by hongminhee
11 points by hongminhee
I note that the implementation is repeated, with just some extra awaits scattered in. You can avoid that using generator functions with yield in place of await, like this:
// helpers:
function split(genFn) {
function runSync(...args) {
const it = genFn(...args);
let next = it.next();
while (true) {
if (next.done) return next.value;
next = it.next(next.value);
}
}
async function runAsync(...args) {
const it = genFn(...args);
let next = it.next();
while (true) {
if (next.done) {
return await next.value;
}
let send = next.value;
try {
send = await send;
} catch (err) {
next = it.throw(err);
continue;
}
next = it.next(send);
}
}
return { sync: runSync, async: runAsync };
}
// usage:
function* impl(parse) {
console.log(yield parse('foo'));
}
let impls = split(impl);
impls.sync((x) => x + ' sync'); // synchronously prints
console.log('sync should have already printed here');
await impls.async(async (x) => { await 0; return x + ' async'; }); // asynchronously prints
Might have some trouble getting TypeScript to like this, but it should be doable.
If you want this wrapped up in a library with some bonus features you can use the gensync library, which I have a writeup of here. But the above little snippet is all you really need.
Couldn't you just run the command or whatever synchronously? I'm not sure async actually buys you anything here.
I’m not that expert on node.js APIs, but in my experience only some of them have synchronous equivalents.