18

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.

4

5 回答 5

13

我知道,这个问题很老了。但是 ramda 有一些很酷的函数来组合 Promise-returning 函数:pipePcomposeP

还可以查看常规compose ( pipe ),它是 Kleisli 实现composeK ( pipeK )。它们允许使用诸如 Future 或 Task 之类的代数结构,它们看起来与 Promise 相同,但进行了惰性求值。

于 2016-02-24T00:43:09.287 回答
6

您可以使用Promise.resolve在 Promise 中“包装”一个值。

getSectionFromDataPromise :: obj -> promise
getSectionFromDataPromise = R.pipe(getSectionFromData , (val) => Promise.resolve(val))

这样,您可以将任何返回正常值的函数提升(提升)为返回承诺的函数。

提升是 FP 中的一个基本概念。您可以将Array.map其视为将转换值的函数提升为转换值数组的函数的函数。

您可以使用Promise.all编写一个比较 Promise 的函数,并且(例如)如果它们不相等则抛出错误。

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]
  })
}

最后,您可以将两者结合起来:

promiseEquals(getSectionFromDataPromise, getSectionFromDb)
  .then(function(val){
    console.log(val)
  })
  .catch(function(val){console.log("Error "+val)})
于 2015-11-30T16:42:28.563 回答
6

pipeP并被composeP弃用。

创建pipeWithPromise它接受一组承诺或函数。

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';
于 2019-12-23T15:50:35.480 回答
1

它不是 ramda,但它会做你想做的事

const { eq } = require('rubico')
/*
getSectionFromDb :: obj -> promise
getSectionFromData :: obj -> number
*/
eq(
  getSectionFromDb,
  getSectionFromData
)({...}) // => Promise { true }

rubico 的 eq 将在引擎盖下解决承诺,因此您获得的承诺getSectionFromDb将在与来自的数字进行比较之前解决getSectionFromData。但是,返回值将是一个布尔值的 Promise,您必须在其他地方解析它。

于 2020-05-20T23:50:59.773 回答
0

您可以创建自定义撰写:https ://gist.github.com/ehpc/2a524b78729ee6b4e8111f89c66d7ff5

于 2020-06-10T11:24:04.707 回答