使用 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,因为我们可以从其他函数中组合它。如果你分解它,我们所做的是在两个不同的地方获取 invoiceamount,但我们可以只获取一个数量数组

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

我们可以将它与 sumsubtract 一起删除,以创建一个完全独立于我们的异步代码的函数

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),
);