I want to transform an imperative Promise
to a functional Task
in a principled fashion:
const record = (type, o) =>
(o[type.name || type] = type.name || type, o);
const thisify = f => f({});
const taskFromPromise = p =>
Task((res, rej) =>
p.then(res)
.catch(x => rej(`Error: ${x}`)));
const Task = task => record(
Task,
thisify(o => {
o.task = (res, rej) =>
task(x => {
o.task = k => k(x);
return res(x);
}, rej);
return o;
}));
const tx = taskFromPromise(Promise.resolve(123)),
ty = taskFromPromise(Promise.reject("reason").catch(x => x));
// ^^^^^ necessary to avoid uncaught error
tx.task(console.log); // 123
ty.task(console.log); // "reason" but should be "Error: reason"
The resolution case works but the rejection doesn't, because Promise
s are eagerly triggered. If I dropped the catch
handler I would have to put the entire computation into a try
/catch
statement. Is there a more viable alternative?