admin管理员组文章数量:1178529
I am looking at handling functions that return promises with Ramda functions other then pipeP. I am trying to compare functions (one of which returns a promise) with equals like this:
getSectionFromDb :: obj -> promise
getSectionFromData :: obj -> number
R.equals(
getSectionFromDb,
getSectionFromData
)
There are two factors at play here. First R.equals will not evaluate functions, but the bigger issue is that I'm comparing a promise to a number.
Is there a functional way of doing this kind of stuff (I know the functions are not referential transparent, but there must be a way of dealing with io)? Is there a Ramda way of doing this?
Thanks.
I am looking at handling functions that return promises with Ramda functions other then pipeP. I am trying to compare functions (one of which returns a promise) with equals like this:
getSectionFromDb :: obj -> promise
getSectionFromData :: obj -> number
R.equals(
getSectionFromDb,
getSectionFromData
)
There are two factors at play here. First R.equals will not evaluate functions, but the bigger issue is that I'm comparing a promise to a number.
Is there a functional way of doing this kind of stuff (I know the functions are not referential transparent, but there must be a way of dealing with io)? Is there a Ramda way of doing this?
Thanks.
Share Improve this question asked Nov 2, 2015 at 21:10 BBSBBS 1,4092 gold badges13 silver badges28 bronze badges 9 | Show 4 more comments5 Answers
Reset to default 14I know, the question is old. But ramda has some cool functions to compose Promise-returning functions: pipeP and composeP.
Also take a look into regular compose (pipe) and it's Kleisli implementation composeK (pipeK). They allow to work with algebraic structures like Future or Task, which look the same as Promise, but lazy-evaluated.
You can use Promise.resolve
to "wrap" a value in a promise.
getSectionFromDataPromise :: obj -> promise
getSectionFromDataPromise = R.pipe(getSectionFromData , (val) => Promise.resolve(val))
This way you can promote (lift) any function that returns a normal value to a one that returns a promise.
Lifting is an essential concept in FP. You can view Array.map
as a function that lifts a function that transforms a value to a function that transforms an array of values.
You can use Promise.all
to write a function that compares promises and (for example) throws an error if they are not equal.
function promiseEquals (f1, f2) {
return Promise.all([f1(), f2()]).then(function(vals) {
if(!R.equals(vals[0], vals[1])) {throw "The values aren't equal"}
return vals[0]
})
}
Lastly you can combine the two:
promiseEquals(getSectionFromDataPromise, getSectionFromDb)
.then(function(val){
console.log(val)
})
.catch(function(val){console.log("Error "+val)})
pipeP
and composeP
got deprecated.
Create pipeWithPromise
which accepts an array of promises or functions.
var pipeWithPromise = R.pipeWith((fun, previousResult) => (previousResult && previousResult.then) ? previousResult.then(fun) : fun(previousResult));
var tasks = [/* sync func */ $ => $ + '1', /* async func */ async $ => await $ + '2'];
var result = await pipeWithPromise(tasks)('state');
// result = 'state12';
It's not ramda, but it'll do what you want
const { eq } = require('rubico')
/*
getSectionFromDb :: obj -> promise
getSectionFromData :: obj -> number
*/
eq(
getSectionFromDb,
getSectionFromData
)({...}) // => Promise { true }
rubico's eq will resolve promises under the hood, so the promise you get from getSectionFromDb
will be resolved before it is compared with the number from getSectionFromData
. The return value will be a Promise of a boolean that you'll have to resolve elsewhere, however.
You can create custom compose: https://gist.github.com/ehpc/2a524b78729ee6b4e8111f89c66d7ff5
本文标签: javascriptHandling asynchronous programming with RamdaStack Overflow
版权声明:本文标题:javascript - Handling asynchronous programming with Ramda - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738042355a2054015.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
lift
theequals
function - first in the promise monad and then in the function applicative; unfortunately Ramda can only lift for lists. – Bergi Commented Nov 2, 2015 at 21:16??? :: (obj -> Promise<number>) -> (obj -> number) -> (obj -> Promise<boolean>)
? – Bergi Commented Nov 2, 2015 at 21:18lift
does work on arbitraryApplicative Functors
. – Scott Sauyet Commented Nov 2, 2015 at 21:24liftN(2, flip(compose(map, equals)))
assuming that your functions implementApplicative
like this and your Promises implementFunctor
– Bergi Commented Nov 2, 2015 at 21:44??? :: (obj -> Promise<number>) -> (obj -> number) -> (obj -> Promise<boolean>)
but I am not sure syntactically how lift should work. – BBS Commented Nov 2, 2015 at 22:17