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