让 R.pipe 与承诺一起工作



Background

我有一个简单的代码,它组成函数来打印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返回一个承诺。我的印象是,如果我将整个代码转换为承诺,pipeP可以工作,但我确实想避免这种情况

我的想法是像 flatMap 这样的东西,也就是 Ramda 中的chain,但这也行不通。

问题

如何在不将所有内容转换为承诺的情况下使此代码工作?

可以在这里找到 MWE

一旦你处理了承诺/任务/未来,就不可避免地必须处理异步数据和程序流

如何在不将所有内容转换为承诺的情况下使此代码工作?

你说的,是说这部分吗?

// ...
phrase();

出于同样的原因,三元运算符?:强制你包含条件的两个分支,异步调用希望你处理承诺/任务/未来的成功分支错误分支

// ...
phrase().then(onSuccess, onError);

当然,没有什么能阻止你做

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

正如raina77ow提到的,不推荐使用pipeP(和composeP(。我们可以通过添加一个简单的then函数来修复您的程序,该函数很容易插入正常的pipe(或compose(函数序列中

const greeting = () => "Hello ";
const dbQuery = str => Promise.resolve( `${str} Mars` );
const then = R.curry((f, p) => p.then(f))
const phrase = R.pipe(
  greeting,
  dbQuery,
  then(R.flip(R.concat)('!'))
);
phrase().then(console.log, console.error);
// Hello Mars!
// => { Promise 'Hello Mars!' }
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

我在下面写了以下帮助程序函数,应该可以解决您的问题。 它平等地处理承诺和非承诺数据。它还检查返回承诺的数组,如果是,则使用 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现在包含then和其他函数,所以最好使用这些函数:

https://ramdajs.com/docs/#andThen

https://ramdajs.com/docs/#otherwise

相关内容

  • 没有找到相关文章

最新更新