admin管理员组

文章数量:1425873

Background

I have a simple code that poses functions to print Hello Mars!:

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

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

phrase();

Problem

I am using pipeP because dbQuery returns a Promise. I am under the impression that pipeP could work if I converted my entire code to promises, but I really do want to avoid that.

My idea was to something something like flatMap, aka chain in Ramda, but that doesn't work either.

Question

How can I make this code work without converting everything into a Promise?

A MWE can be found here

Background

I have a simple code that poses functions to print Hello Mars!:

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

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

phrase();

Problem

I am using pipeP because dbQuery returns a Promise. I am under the impression that pipeP could work if I converted my entire code to promises, but I really do want to avoid that.

My idea was to something something like flatMap, aka chain in Ramda, but that doesn't work either.

Question

How can I make this code work without converting everything into a Promise?

A MWE can be found here

Share Improve this question asked Jan 9, 2018 at 14:07 Flame_PhoenixFlame_Phoenix 17.7k40 gold badges146 silver badges284 bronze badges 6
  • How about just writing it normally, without Ramda? – Ry- Commented Jan 9, 2018 at 14:10
  • 1 Check discussion in this thread - as well as discussions linked in there. In short, Ramda team sees pipeP (and poseP) as old way of doing things. – raina77ow Commented Jan 9, 2018 at 14:20
  • @raina77ow That could work if greeting was a Promise. However, it isn't. When the first value in the pipe is not a position, how could you make it work? – Flame_Phoenix Commented Jan 9, 2018 at 14:27
  • You want to pose a nullary function with an action that returns a Promise. This just doesn't work and Ramda is right to plain. – user6445533 Commented Jan 9, 2018 at 14:40
  • I know why Ramda plains. I never said Ramda was wrong. I made that clear in my post and even suggest fixes that i don't like. – Flame_Phoenix Commented Jan 9, 2018 at 14:44
 |  Show 1 more ment

3 Answers 3

Reset to default 3

Once you are dealing with Promise/Task/Future, there's no avoiding having to handle asynchronous data and program flow

How can I make this code work without converting everything into a Promise?

By everything, do you mean this part?

// ...
phrase();

For the same reason the ternary operator ?: forces you to include both branches of the conditional, asynchronous calls expect you to handle both the successful and the erroneous branches of the Promise/Task/Future

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

Of course there's nothing stopping you from doing

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

main()

And as raina77ow mentions, pipeP (and poseP) are not remended. We can fix your program by adding a simple then function which is easily inserted in a normal pipe (or pose) sequence of functions

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./ajax/libs/ramda/0.25.0/ramda.js"></script>

I wrote the following helper function below which should solve your problem. It deals with promise and non-promise data equally. It also checks for arrays with promises being returned and, if so, handles them with Promise.all. As expected, its final result will be a promise.

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)
}

Here is how to use asyncPipe for your original code problem:

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 now includes then and otherwise functions, so best to use these:

https://ramdajs./docs/#andThen

https://ramdajs./docs/#otherwise

本文标签: javascriptMake Rpipe work with a PromiseStack Overflow