Javascript 用承诺让R.管道工作? 背景

Javascript 用承诺让R.管道工作? 背景,javascript,functional-programming,ramda.js,Javascript,Functional Programming,Ramda.js,我有一个简单的代码,它包含打印函数Hello Mars: var greeting = () => "Hello "; var dbQuery = str => Promise.resolve( `${str} Mars` ); var phrase = R.pipeP( greeting, dbQuery, R.flip( R.concat )("!") ); phrase(); 问题 我使用的是pipeP,因为dbQuery返回一个承诺。我的印象是

我有一个简单的代码,它包含打印函数
Hello Mars

var greeting = () => "Hello ";
var dbQuery = str => Promise.resolve( `${str} Mars` );

var phrase = R.pipeP(
    greeting,
    dbQuery, 
    R.flip( R.concat )("!")
);

phrase();
问题 我使用的是
pipeP
,因为
dbQuery
返回一个承诺。我的印象是,如果我将整个代码转换为承诺,
pipe
可以工作,但是我真的想避免这种情况

我的想法是在Ramda中创建类似于
flatMap
,也称为
chain
,但这也不起作用

问题: 如果不将所有内容转换为承诺,我如何使此代码正常工作


一旦您处理Promise/Task/Future,就不可避免地要处理异步数据和程序流

如果不将所有内容转换为承诺,我如何使此代码正常工作

你指的是这部分吗

// ...
phrase();
出于同样的原因,三元运算符
?:
强制您包括条件调用的两个分支,异步调用期望您处理Promise/Task/Future的成功分支和错误分支

// ...
phrase().then(onSuccess, onError);
当然,没有什么能阻止你这么做

const main = () =>
  phrase().then(console.log, console.error)

main()
如前所述,Pippep(和composeP)是。我们可以通过添加一个简单的
然后
函数来修复您的程序,该函数很容易插入到正常的
管道
(或
组合
)函数序列中

const问候语=()=>“你好”;
constdbquery=str=>Promise.resolve(`${str}Mars`);
const then=R.curry((f,p)=>p.then(f))
常量短语=R.pipe(
招呼
dbQuery,
然后(R.flip(R.concat)(“!”))
);
短语().then(console.log,console.error);
//你好,火星!
//=>{Promise'Hello Mars!'}

Ramda现在包括then和Others函数,因此最好使用这些函数:


我在下面编写了以下帮助函数,可以解决您的问题。它平等地处理承诺和非承诺数据。它还检查返回承诺的数组,如果是,则使用
Promise.all
处理它们。正如预期的那样,它的最终结果将是一个承诺

function asyncPipe(...funcs){
  const reducer = async (val, func) => func(await (Array.isArray(val) ? Promise.all(val): val));
  return async val => await R.reduce(reducer, val, funcs)
}
以下是如何使用
asyncPipe
解决原始代码问题:

function asyncPipe(...funcs){
  const reducer = async (val, func) => func(await (Array.isArray(val) ? Promise.all(val): val));
  return async val => await R.reduce(reducer, val, funcs)
}

var greeting = () => "Hello ";
var dbQuery = str => Promise.resolve( `${str} Mars` );

var phrase = asyncPipe(
    greeting,
    dbQuery, 
    R.flip( R.concat )("!")
);

phrase().then(console.log);

不带Ramda的情况下,正常地写它怎么样?检查讨论-以及在那里链接的讨论。简言之,Ramda团队认为
pippep
(和
composeP
)是一种古老的做事方式。@raina77如果
问候
是一种承诺,那么这可能会奏效。然而,事实并非如此。当管道中的第一个值不是合成值时,如何使其工作?您希望使用返回
承诺的操作合成一个空函数。这根本不起作用,拉姆达抱怨是对的。我知道拉姆达为什么抱怨。我从没说过拉姆达错了。我在我的帖子中明确了这一点,甚至提出了我不喜欢的修复建议。我希望在Ramda中看到
then
helper函数。你的例子解释了我需要知道的一切。谢谢不知怎的,拉姆达团队在这个问题上偏离了方向,但我们做到了。@ScottSauyet你不打算反对
pippep
使用期货吗?我们打算反对
pippep
,因为我们更喜欢像
Futures
这样的合法类型,我们将添加
,然后添加
,以允许Promise用户仍能获得合理的体验。我们仍在计划,但最近进展缓慢。如果您想在链中添加更多功能,该怎么办?比如
constphrase=R.pipe(问候语,dbQuery,然后(R.flip(R.concat)(“!”)),R.concat(“!”)。在dbQuery之后是否始终需要使用
然后