使用 Ramda 处理异步编程

Handling asynchronous programming with Ramda

我正在研究 return 承诺使用 Ramda 函数而不是 pipeP 的处理函数。我正在尝试将函数(其中一个 return 是一个承诺)与这样的等式进行比较:

getSectionFromDb :: obj -> promise
getSectionFromData :: obj -> number

R.equals(
    getSectionFromDb,
    getSectionFromData
)

这里有两个因素在起作用。首先 R.equals 不会评估函数,但更大的问题是我将承诺与数字进行比较。

有没有一种功能性的方法来做这种事情(我知道这些功能不是引用透明的,但必须有一种处理 io 的方法)?有 Ramda 的方法吗?

谢谢。

您可以使用 Promise.resolve 来 "wrap" 承诺中的值。

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

通过这种方式,您可以将任何 returns 正常值的函数提升(提升)为 returns 承诺的函数。

提升是函数式编程中的一个基本概念。您可以将 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)})

我知道,这个问题很老了。但是 ramda 有一些很酷的函数来组合 Promise 返回函数:pipeP and composeP.

另请查看常规 compose (pipe) and it's Kleisli implementation composeK (pipeK)。它们允许使用像 Future 或 Task 这样的代数结构,它们看起来与 Promise 相同,但是是惰性求值的。

pipePcomposeP 已弃用。

创建 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';

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

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

rubico 的 eq 将在幕后解决承诺,因此您从 getSectionFromDb 获得的承诺将在与 getSectionFromData 的数字进行比较之前解决。然而,return 值将是一个布尔值的 Promise,您必须在其他地方解析它。

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