用于排除数组对象的函数

时间:2015-12-11 11:36:37

标签: javascript coffeescript

我有一个我正在创建的规则引擎的代码

getSKULine = (s, priceList) ->
  rdb.getDiscountMap(s, priceList)
    .then (result) ->
      console.log result
      if result.cdLine is "T" and result.cdOver is "F" then result else null

exports.getRules = (user) ->
  if !user
    Promise.resolve null
  else
    priceList = user.company.opera.terms.priceList
    territory = user.company.opera.account.territory
    country = user.company.country
    emailId = user.emailId
    account = user.company._id
    trade_sector = user.company.trade_sector
    discountCache = {}
    cond = {
      'status': 'published'
      'type': 'price'
      "to" : { "$gte" : Date.now() }
      "unselPriceLists": { "$nin": [ priceList ] }
      "unselReps": { "$nin": [ territory ] }
      "unselCountries": { "$nin": [ country ] }
      "unselAccounts": { "$nin": [ account ] }
      "unselCompanyTypes": { "$nin": [ trade_sector ] }
    }
    Rule.findAllPr(cond)
    .then (rules) ->
      _.zipObject rules.map (r) ->
        skus = _.zipObject(r.skus.map((s) ->
          if getSKULine(s, priceList)
            [
              s
              r.discount
            ]
          else null
        ))
        extended = _.extend(discountCache, skus)
    .then (skus) ->
      discountCache
if getSKULine(s, priceList)中的

我正在检查具有

条目的redis缓存
{ sku: 'SA61-MNA',
  priceList: 'DISTSD',
  quantity1: 1,
  quantity2: 10,
  quantity3: 50,
  price1: 263,
  price2: 228,
  price3: 208,
  cdLine: 'T',
  cdOver: 'T',
  cdFundec: 2 }
{ sku: 'SA61-MPL',
  priceList: 'DISTSD',
  quantity1: 1,
  quantity2: 10,
  quantity3: 50,
  price1: 263,
  price2: 228,
  price3: 208,
  cdLine: 'T',
  cdOver: 'T',
  cdFundec: 2 }

我想只返回一个对象,其中cdLine是' T'和cdOver是' F'但它似乎不起作用,因为我的discountCache对象仍包含这些行?

我缺少什么,非常感谢任何建议

1 个答案:

答案 0 :(得分:0)

我相信你会想要使用Array.prototype.reduce代替地图,这样你就可以有条件地添加getSKULine返回的结果。像这样:

skus = _.zipObject (r.skus.reduce(((accum, s) ->
  obj = getSKULine(s, priceList)
  if obj? and obj.cdLine is 'T' and obj.cdOver is 'F'
    accum.push([s, r.discount)
  accum), [])

现在您正在使用reduce代替map,您不需要使用lodash函数来转换结果:

skus = r.skus.reduce(((accum, s) ->
  obj = getSKULine(s, priceList)
  if obj? and obj.cdLine is 'T' and obj.cdOver is 'F'
    accum[s] = r.discount
  accum), {})

修改

很抱歉只是意识到getSKULine会返回一个Promise而不是一个对象。这就是为什么您的原始代码不起作用的原因:您正在混合同步和异步代码。由于函数返回Promise,结果将始终是真实的,getSKULine中的条件过滤不会做任何事情。实际上,整个功能是不必要的。你需要做这样的事情:

#map over the skus to get an array of Promises, use Promise.all
#to convert to a Promise of an array of objects from the Redis
#cache
skuLines = Promise.all(r.skus.map((s) -> rdb.getDiscountMap(s, priceList)));
result = skuLines.then((arr) -> arr.reduce(((accum, obj, i) ->

  #grabbing the original sku
  s = r.skus[i]

  #moved the filtering from getSKULine to here
  if obj? obj.cdLine is 'T' and obj.cdOver is 'F' then accum[s] = r.discount
  accum), {}))

要从结果中获取结束对象,您需要在其上调用then。像result.then((res) -> doStuff(res))这样的东西。请记住,您无法取消选择'一个Promise,你总是需要调用then方法来获取里面的值。原来的getSKULines出了什么问题,你认为你正在返回null,但是由于then自动将结果包装到另一个Promise中,你实际上是在返回一个 Promise null