简体   繁体   中英

How to transform an imperative Promise to a functional Task?

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?

You don't need .catch(x => x) , which turns your rejected promise into an resolved one. You shouldn't get an "uncaught error" since you have a catch inside your taskFromPromise function. Removing the .catch(x => x) does work and lands you in .catch(x => rej(`Error: ${x}`)) instead.

However removing .catch(x => x) does throw "TypeError: rej is not a function". From your code sample it it seems like your .task(...) (in tx.task(...) and ty.task(...) ) expects two functions. The first one is called if the promise resolves, the second one if the promise is rejected. Providing both functions leaves me with a working code snippet.

 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) => // expects two functions task(x => { o.task = k => k(x); return res(x); }, rej); return o; })); const tx = taskFromPromise(Promise.resolve(123)), ty = taskFromPromise(Promise.reject("reason")); // removed.catch(x => x) tx.task(console.log, console.log); // provide two functions ty.task(console.log, console.log); // ^ ^ // if resolved if rejected

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM