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 intothen
and work with the promises explicitly. At best you can useposeP
. – 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 expressionawait Promise.all(R.map(uOrder => uOrder.invoice, await order.upstreamOrders))
. – Bergi Commented Oct 13, 2017 at 12:56
1 Answer
Reset to default 6I 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),
);