Ramda JS как отобразить значение c, используя файл 2 json - PullRequest
0 голосов
/ 24 января 2020

проблема, с которой я столкнулся, - это использование файла 2 json для отображения состояния события, и я не уверен, как это сделать в ramda

const input1 = {
              data: {
                memberId: 12345,
                orderStatus: pack
              },
              Time: '2019-08-12T08:55:28Z',
              statusType: 'order',
            }

const input2 = {
              data: {
                memberId: 12345,
                deliveryStatus: dispatch
              },
              Time: '2019-08-12T08:55:28Z',
              statusType: 'delivery',
            }

const input3 = {
              data: {
                memberId: 12345,
              },
              Time: '2019-08-12T08:55:28Z',
              statusType: 'new',
            }

const status = {
  'order': {
      orderStatus: {
        pack: 'order is being pack',
        cancelled: 'cancel order'
    },
  },
  'delivery': {
      deliveryStatus: {
        pending: 'pending',
        dispatch: 'order has been delivered'
    },
  },
  'new': 'newly made'
}
  1. Вход в консольный журнал1: " заказ упаковывается "
  2. Вход в консольный журнал2:" заказ доставлен "
  3. Вход в консольный журнал3:" только что сделан "

спасибо

1 Ответ

1 голос
/ 27 января 2020

Уродливое решение

Мы можем сделать это без Рамды, несколько сложным образом:

const statusHandler = (statuses) => {
  const handlers = Object .fromEntries (Object .entries (status)
    .map (([name, val]) => typeof val == 'string'
      ? [name, () => val]
      : [name, ({data}) => val [name + 'Status'] [data [name + 'Status']]]
    ))
 
  return (item) => handlers [item .statusType] (item)
}
 
const status = {
  order: {
    orderStatus: {
      pack: 'order is being pack', 
      cancelled: 'cancel order'
    }
  }, 
  delivery: {
    deliveryStatus: {
      pending: 'pending', 
      dispatch: 'order has been delivered'
    }
  }, 
  new: 'newly made'
}
 
const getStatus = statusHandler (status)
 
const input1 = {data: {memberId: 12345, orderStatus: 'pack'}, Time: '2019-08-12T08:55:28Z', statusType: 'order'}
const input2 = {data: {memberId: 12345, deliveryStatus: 'dispatch'}, Time: '2019-08-12T08:55:28Z', statusType: 'delivery'}
const input3 = {data: {memberId: 12345}, Time: '2019-08-12T08:55:28Z', statusType: 'new'}
 
console .log (getStatus (input1))
console .log (getStatus (input2))
console .log (getStatus (input3))

Я не вижу, чтобы Рамда предложил бы здесь много упрощений, возможно, немного сократив вещи с помощью fromPairs и toPairs вместо Object .fromEntries и Object .entries или даже лучше с map Рамды, который работает с объектами, и, возможно, с некоторым дополнительным упрощением с использованием pipe, но это не решило бы главной проблемы с этим, что ключи, которые мы ищем, должны быть сконструированы и что наш объект конфигурации status содержит две разные структуры, а не согласован для всех.

Я понятия не имею, навязывается ли вам этот объект status, и вам просто нужно иметь с ним дело, или если он твоя собственная конструкция. Ниже я расскажу о способах его очистки, но, во-первых, есть одна вещь, которую мы могли бы сделать для обработки как минимум одного возможного сбоя:

Обработка пропущена statusType s

Если statusType нет в нашем списке типов, тогда это не удастся. Возможно, ваши данные достаточно непротиворечивы, чтобы этого никогда не случалось, но я слишком часто видел, как будто невозможные ситуации с данными приводят к отказу приложения. Так что это расширение может сделать его чище.

const statusHandler = (statuses) => {
  const handlers = Object .fromEntries (Object .entries (status)
    .map (([name, val]) => typeof val == 'string'
      ? [name, () => val]
      : [name, ({data}) => val [name + 'Status'] [data [name + 'Status']]]
    ))
  const defaultHandler = () => 'unknown status type'  // New line

  return (item) => (handlers [item .statusType] || defaultHandler) (item)  // Updated
}

Это позволит нам обрабатывать случаи, подобные этому:

const input4 = {data: {memberId: 12345}, Time: '2019-08-12T08:55:28Z', statusType: 'foobar'}

getStatus (input4) //=> unknown status type

Очистка объекта конфигурации

Сложность здесь заключается в пределах объекта конфигурации. Мы обрабатываем корпус new с другой структурой, отличной от order и delivery. И мы вкладываем сообщения в то, что выглядит как ненужный дополнительный уровень (почему бы не переместить содержимое orderStatus и deliveryStatus их родителям?) Как я уже сказал, это может быть существующая структура, которую мы не можем контролировать, и ответ выше может быть лучшим, что мы можем сделать. Но если у нас есть контроль над этой структурой, то это более явно и приводит к более чистому коду:

const statusHandler = (statuses) => (item) => {
  const type = statuses [item .statusType] || statuses ['*']
  return type [item .data [item .statusType + 'Status'] || '*']
}

const status = {
  order: {
    pack: 'order is being pack', 
    cancelled: 'cancel order',
    '*': 'unknown order status'
  }, 
  delivery: {
    pending: 'pending', 
    dispatch: 'order has been delivered',
    '*': 'unknown delivery status'
  }, 
  new: {
    '*': 'newly made'   
  },
  '*': {
    '*': 'unknown status type'
  }
}

Это также объясняет еще один потенциальный сбой:

const input5 = {data: {memberId: 12345, status: 'collection'}, Time: '2019-08-12T08:55:28Z', statusType: 'order'}

getStatus (input5) //=> unknown order status

У нас, вероятно, есть на самом деле увеличил количество строк здесь из-за дополнений к объекту конфигурации. Но в целом, это намного проще . Наш объект конфигурации полностью описывает вид вывода, который мы получаем для любой комбинации статуса и стадии. Наш код просто переводит это в функцию из нашего элемента данных.

Вы можете увидеть его в действии в следующем фрагменте:

const statusHandler = (statuses) => (item) => {
  const type = statuses [item .statusType] || statuses ['*']
  return type [item .data [item .statusType + 'Status'] || '*']
}

const status = {
  order: {
    pack: 'order is being pack', 
    cancelled: 'cancel order',
    '*': 'unknown order status'
  }, 
  delivery: {
    pending: 'pending', 
    dispatch: 'order has been delivered',
    '*': 'unknown delivery status'
  }, 
  new: {
    '*': 'newly made'   
  },
  '*': {
    '*': 'unknown status type'
  }
}
 
const getStatus = statusHandler (status)
 
const input1 = {data: {memberId: 12345, orderStatus: 'pack'}, Time: '2019-08-12T08:55:28Z', statusType: 'order'}
const input2 = {data: {memberId: 12345, deliveryStatus: 'dispatch'}, Time: '2019-08-12T08:55:28Z', statusType: 'delivery'}
const input3 = {data: {memberId: 12345}, Time: '2019-08-12T08:55:28Z', statusType: 'new'}
const input4 = {data: {memberId: 12345}, Time: '2019-08-12T08:55:28Z', statusType: 'foobar'}
const input5 = {data: {memberId: 12345, status: 'collection'}, Time: '2019-08-12T08:55:28Z', statusType: 'order'}
 
console .log (getStatus (input1))
console .log (getStatus (input2))
console .log (getStatus (input3))
console .log (getStatus (input4))
console .log (getStatus (input5))

Устранение дублирования в наших элементах

Наконец, даже если у нас есть контроль над этим объектом конфигурации, мы можем не иметь контроля над объектами входных данных. Но если мы это сделаем, то в этом есть некоторая избыточность, которая не только не нужна, но и заставляет нас делать раздражающие манипуляции со строками в нашей функции:

const input1 = {
              data: {
                memberId: 12345,
                <b>order</b>Status: pack
              },
              Time: '2019-08-12T08:55:28Z',
              statusType: '<b>order</b>',
            }

Мы объявляем statusType из order, но затем установите orderStatus на pack. Существует явный аргумент для замены orderStatus просто status. Таким образом, если бы у нас также был контроль над этими данными, у нас были бы более согласованные данные, и наша функция могла бы быть еще проще.

Мы можем увидеть эту возможность в следующем фрагменте:

const statusHandler = (statuses) => (item) => {
  const type = statuses [item .statusType] || statuses ['*']
  return type [item .data .status || '*'] || type ['*']
}

const status = {
  order: {
    pack: 'order is being pack', 
    cancelled: 'cancel order',
    '*': 'unknown order status'
  }, 
  delivery: {
    pending: 'pending', 
    dispatch: 'order has been delivered',
    '*': 'unknown delivery status'
  }, 
  new: {
    '*': 'newly made'   
  },
  '*': {
    '*': 'unknown status type'
  }
}
 
const getStatus = statusHandler (status)
 
const input1 = {data: {memberId: 12345, status: 'pack'}, Time: '2019-08-12T08:55:28Z', statusType: 'order'}
const input2 = {data: {memberId: 12345, status: 'dispatch'}, Time: '2019-08-12T08:55:28Z', statusType: 'delivery'}
const input3 = {data: {memberId: 12345}, Time: '2019-08-12T08:55:28Z', statusType: 'new'}
const input4 = {data: {memberId: 12345}, Time: '2019-08-12T08:55:28Z', statusType: 'foobar'}
const input5 = {data: {memberId: 12345, status: 'collection'}, Time: '2019-08-12T08:55:28Z', statusType: 'order'}
 
console .log (getStatus (input1))
console .log (getStatus (input2))
console .log (getStatus (input3))
console .log (getStatus (input4))
console .log (getStatus (input5))

Уроки

Мы можем упростить наш код, сделав наши структуры данных более простыми и согласованными. Это позволяет нам сделать всю нашу систему более декларативной. Обратите внимание, что конечная функция не только проще, но и с гораздо большей вероятностью может быть многократно использована в разных частях нашего приложения или в разных приложениях.

...