最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Using Ramda to handle promise and await - Stack Overflow

programmeradmin1浏览0评论

I have a piece of code which was written using Lodash:

    const profit =
      price -
      _.sumBy(
        await Promise.all(
          map(uOrder => uOrder.invoice, await order.upstreamOrders),
        ),
        'amount',
      );

I want to change it using Ramda, after thinking about it and reading some documentation, I wrote this:

    const result = Rpose(
      R.pick(['amount']),
      await Promise.all(),
      R.map(await order.upstreamOrders, uOrder.invoice),
    );

of course it's wrong and not working, but its's my first approach and I want to know how to handle a situation like this using Ramda perfectly and in a functional way. How I can perform this?

Also order of object is array of following sample:

    { 
    "_id" : ObjectId("59dce1f92d57920d3e62bdbc"), 
    "updatedAt" : ISODate("2017-10-10T15:06:34.111+0000"), 
    "createdAt" : ISODate("2017-10-10T15:06:33.996+0000"), 
    "_customer" : ObjectId("59dce1f92d57920d3e62bd44"), 
    "_distributor" : ObjectId("59dce1f92d57920d3e62bd39"), 
    "status" : "NEW", 
    "cart" : [
        {
            "count" : NumberInt(1), 
            "_item" : ObjectId("59dce1f92d57920d3e62bd57"), 
            "_id" : ObjectId("59dce1f92d57920d3e62bdc1")
        }, 
        {
            "count" : NumberInt(1), 
            "_item" : ObjectId("59dce1f92d57920d3e62bd5c"), 
            "_id" : ObjectId("59dce1f92d57920d3e62bdc0")
        }, 
        {
            "count" : NumberInt(1), 
            "_item" : ObjectId("59dce1f92d57920d3e62bd61"), 
            "_id" : ObjectId("59dce1f92d57920d3e62bdbf")
        }, 
        {
            "count" : NumberInt(1), 
            "_item" : ObjectId("59dce1f92d57920d3e62bd66"), 
            "_id" : ObjectId("59dce1f92d57920d3e62bdbe")
        }, 
        {
            "count" : NumberInt(1), 
            "_item" : ObjectId("59dce1f92d57920d3e62bd6b"), 
            "_id" : ObjectId("59dce1f92d57920d3e62bdbd")
        }
    ], 
    "_upstreamOrders" : [
        "4545643499"
    ], 
    "key" : "4592846350", 
    "__v" : NumberInt(1), 
    "_invoice" : "0811260909610702"
}

I have a piece of code which was written using Lodash:

    const profit =
      price -
      _.sumBy(
        await Promise.all(
          map(uOrder => uOrder.invoice, await order.upstreamOrders),
        ),
        'amount',
      );

I want to change it using Ramda, after thinking about it and reading some documentation, I wrote this:

    const result = R.pose(
      R.pick(['amount']),
      await Promise.all(),
      R.map(await order.upstreamOrders, uOrder.invoice),
    );

of course it's wrong and not working, but its's my first approach and I want to know how to handle a situation like this using Ramda perfectly and in a functional way. How I can perform this?

Also order of object is array of following sample:

    { 
    "_id" : ObjectId("59dce1f92d57920d3e62bdbc"), 
    "updatedAt" : ISODate("2017-10-10T15:06:34.111+0000"), 
    "createdAt" : ISODate("2017-10-10T15:06:33.996+0000"), 
    "_customer" : ObjectId("59dce1f92d57920d3e62bd44"), 
    "_distributor" : ObjectId("59dce1f92d57920d3e62bd39"), 
    "status" : "NEW", 
    "cart" : [
        {
            "count" : NumberInt(1), 
            "_item" : ObjectId("59dce1f92d57920d3e62bd57"), 
            "_id" : ObjectId("59dce1f92d57920d3e62bdc1")
        }, 
        {
            "count" : NumberInt(1), 
            "_item" : ObjectId("59dce1f92d57920d3e62bd5c"), 
            "_id" : ObjectId("59dce1f92d57920d3e62bdc0")
        }, 
        {
            "count" : NumberInt(1), 
            "_item" : ObjectId("59dce1f92d57920d3e62bd61"), 
            "_id" : ObjectId("59dce1f92d57920d3e62bdbf")
        }, 
        {
            "count" : NumberInt(1), 
            "_item" : ObjectId("59dce1f92d57920d3e62bd66"), 
            "_id" : ObjectId("59dce1f92d57920d3e62bdbe")
        }, 
        {
            "count" : NumberInt(1), 
            "_item" : ObjectId("59dce1f92d57920d3e62bd6b"), 
            "_id" : ObjectId("59dce1f92d57920d3e62bdbd")
        }
    ], 
    "_upstreamOrders" : [
        "4545643499"
    ], 
    "key" : "4592846350", 
    "__v" : NumberInt(1), 
    "_invoice" : "0811260909610702"
}
Share Improve this question edited Oct 9, 2019 at 1:27 Max 1,0601 gold badge12 silver badges20 bronze badges asked Oct 12, 2017 at 6:18 amiramir 2,5834 gold badges25 silver badges51 bronze badges 2
  • await is keyword, not a function that can be posed. You need to desugar it into then and work with the promises explicitly. At best you can use poseP. – Bergi Commented Oct 13, 2017 at 12:54
  • TBH, I don't see why you would want to use pose at all, there's nothing you need to change about the expression await Promise.all(R.map(uOrder => uOrder.invoice, await order.upstreamOrders)). – Bergi Commented Oct 13, 2017 at 12:56
Add a ment  | 

1 Answer 1

Reset to default 6

I think it'd be a good start to break down what exactly the original function is doing

const profit =
  price - // subtract the result
  _.sumBy(
    await Promise.all(
      // Wait for upstreamOrders to resolve, and grab the 'invoice'
      // key for each
      map(uOrder => uOrder.invoice, await order.upstreamOrders),
    ),
    // calculate the sum of the invoices, based on the 'amount' key
    'amount',
  );

With that in mind we can break down those steps, and separate the calculations (synchronous) from the data (async)

Ramda doesn't have a sumBy, as we can pose that from other functions. If you break it down, what we did was grab the invoice and the amount in two separate places, but we can just grab an array of amounts with

map(path(['invoice', 'amount']))

And we can drop that alongside a sum and subtract to create a function which is entirely independent from our async code

const calculateProfits = (price, orders) => pose(
  subtract(price),
  sum,
  map(path(['invoice', 'amount'])),
)(orders)

Allowing us to do something like:

const profit = calculateProfits(price, await order.upstreamOrders)

Or if calculateProfits was curried (and I'm not sure how upstreamOrders works, is it a getter that returns a promise?)

const getUpstreamOrders = order => order.upstreamOrders

getUpstreamOrders(order)
  .then(calculateProfits(price))
  .then(profits => {
    // Do what you want with the profits
  })

Finally, a few notes on the initial attempt

const result = R.pose(
  R.pick(['amount']),

  // Promise.all is being called without any arguments
  // it doesn't really fit within `pose` anyway, but if we were
  // feeding an array of promises through, we'd want to just
  // put `Promise.all,`
  await Promise.all(),

  // the arguments here should be the other way around, we're
  // mapping over upstreamOrders, and the data es last
  // uOrder isn't available in this scope, previously it was
  // `uOrder => uOrder.invoice`,
  // invoking a function and returning the invoice for that order
  R.map(await order.upstreamOrders, uOrder.invoice),
);
发布评论

评论列表(0)

  1. 暂无评论