使用 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 相同,但是是惰性求值的。
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';
它不是 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
我正在研究 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 相同,但是是惰性求值的。
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';
它不是 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