使用 Ramda 处理 promise 和 await
Using Ramda to handle promise and await
我有一段代码是用 Lodash 写的:
const profit =
price -
_.sumBy(
await Promise.all(
map(uOrder => uOrder.invoice, await order.upstreamOrders),
),
'amount',
);
我想用Ramda来改,经过思考和阅读一些文档,我写了这个:
const result = R.compose(
R.pick(['amount']),
await Promise.all(),
R.map(await order.upstreamOrders, uOrder.invoice),
);
当然这是错误的并且不起作用,但这是我的第一种方法,我想知道如何使用 Ramda 以功能性的方式完美地处理这种情况。我该如何执行此操作?
对象的顺序也是以下示例的数组:
{
"_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"
}
我认为分解原始函数的确切功能是一个很好的开始
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',
);
考虑到这一点,我们可以分解这些步骤,并将计算(同步)与数据(异步)分开
Ramda 没有 sumBy
,因为我们可以从其他函数中组合它。如果你分解它,我们所做的是在两个不同的地方获取 invoice
和 amount
,但我们可以只获取一个数量数组
map(path(['invoice', 'amount']))
我们可以将它与 sum
和 subtract
一起删除,以创建一个完全独立于我们的异步代码的函数
const calculateProfits = (price, orders) => compose(
subtract(price),
sum,
map(path(['invoice', 'amount'])),
)(orders)
允许我们做类似的事情:
const profit = calculateProfits(price, await order.upstreamOrders)
或者如果 calculateProfits
被柯里化了(而且我不确定 upstreamOrders 是如何工作的,getter 是 returns 一个承诺吗?)
const getUpstreamOrders = order => order.upstreamOrders
getUpstreamOrders(order)
.then(calculateProfits(price))
.then(profits => {
// Do what you want with the profits
})
最后,关于初次尝试的几点说明
const result = R.compose(
R.pick(['amount']),
// Promise.all is being called without any arguments
// it doesn't really fit within `compose` 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 comes 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),
);
我有一段代码是用 Lodash 写的:
const profit =
price -
_.sumBy(
await Promise.all(
map(uOrder => uOrder.invoice, await order.upstreamOrders),
),
'amount',
);
我想用Ramda来改,经过思考和阅读一些文档,我写了这个:
const result = R.compose(
R.pick(['amount']),
await Promise.all(),
R.map(await order.upstreamOrders, uOrder.invoice),
);
当然这是错误的并且不起作用,但这是我的第一种方法,我想知道如何使用 Ramda 以功能性的方式完美地处理这种情况。我该如何执行此操作?
对象的顺序也是以下示例的数组:
{
"_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"
}
我认为分解原始函数的确切功能是一个很好的开始
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',
);
考虑到这一点,我们可以分解这些步骤,并将计算(同步)与数据(异步)分开
Ramda 没有 sumBy
,因为我们可以从其他函数中组合它。如果你分解它,我们所做的是在两个不同的地方获取 invoice
和 amount
,但我们可以只获取一个数量数组
map(path(['invoice', 'amount']))
我们可以将它与 sum
和 subtract
一起删除,以创建一个完全独立于我们的异步代码的函数
const calculateProfits = (price, orders) => compose(
subtract(price),
sum,
map(path(['invoice', 'amount'])),
)(orders)
允许我们做类似的事情:
const profit = calculateProfits(price, await order.upstreamOrders)
或者如果 calculateProfits
被柯里化了(而且我不确定 upstreamOrders 是如何工作的,getter 是 returns 一个承诺吗?)
const getUpstreamOrders = order => order.upstreamOrders
getUpstreamOrders(order)
.then(calculateProfits(price))
.then(profits => {
// Do what you want with the profits
})
最后,关于初次尝试的几点说明
const result = R.compose(
R.pick(['amount']),
// Promise.all is being called without any arguments
// it doesn't really fit within `compose` 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 comes 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),
);