让 R.pipe 使用 Promise?
Make R.pipe work with a Promise?
背景
我有一个简单的代码,可以组合函数来打印 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
returns 一个 Promise。我的印象是,如果我将整个代码转换为 promise,pipeP
就可以工作,但是 我真的很想避免这种情况。
我的想法是 flatMap
,在 Ramda 中又名 chain
,但这也行不通。
问题
如何在不将所有内容都转换为 Promise 的情况下使此代码工作?
一旦处理 Promise/Task/Future,就不可避免地要处理异步数据和程序流
How can I make this code work without converting everything into a Promise?
一切,你指的是这一部分吗?
// ...
phrase();
出于同样的原因,三元运算符 ?:
强制您包括 both 个条件分支,异步调用希望您处理两个成功的 和Promise/Task/Future
的错误分支
// ...
phrase().then(onSuccess, onError);
当然没有什么能阻止你做
const main = () =>
phrase().then(console.log, console.error)
main()
和raina77ow mentions, pipeP (and composeP) are not recommended一样。我们可以通过添加一个简单的 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>
Ramda 现在包含 then 和 otherwise 函数,所以最好使用这些函数:
我在下面编写了以下辅助函数,应该可以解决您的问题。它平等地处理承诺和非承诺数据。它还检查返回承诺的数组,如果是,则使用 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);
背景
我有一个简单的代码,可以组合函数来打印 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
returns 一个 Promise。我的印象是,如果我将整个代码转换为 promise,pipeP
就可以工作,但是 我真的很想避免这种情况。
我的想法是 flatMap
,在 Ramda 中又名 chain
,但这也行不通。
问题
如何在不将所有内容都转换为 Promise 的情况下使此代码工作?
一旦处理 Promise/Task/Future,就不可避免地要处理异步数据和程序流
How can I make this code work without converting everything into a Promise?
一切,你指的是这一部分吗?
// ...
phrase();
出于同样的原因,三元运算符 ?:
强制您包括 both 个条件分支,异步调用希望您处理两个成功的 和Promise/Task/Future
// ...
phrase().then(onSuccess, onError);
当然没有什么能阻止你做
const main = () =>
phrase().then(console.log, console.error)
main()
和raina77ow mentions, pipeP (and composeP) are not recommended一样。我们可以通过添加一个简单的 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>
Ramda 现在包含 then 和 otherwise 函数,所以最好使用这些函数:
我在下面编写了以下辅助函数,应该可以解决您的问题。它平等地处理承诺和非承诺数据。它还检查返回承诺的数组,如果是,则使用 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);