#9 Условия if else в Ramda

poster
В этом видео мы с вами разберем, как удобнее писать условия if else с помощью Ramda.
Понравилось? Поделитесь с друзьями!
Понравилось?
Поделитесь с друзьями!
Комментарии
Текст видео

В этом видео мы с вами разберем, как удобнее писать условия if else с помощью Ramda.

Представим себе, что нам нужно написать функцию, которая принимает на вход объект (в нашем случае это будет видео), проверяет поле HD внутри объекта и возвращает необходимое нам поле.

const getVideoFilepath = video =>
  video.isHD ? video['720p'] : video['480p']

const video = {
  '720p': 'funny-video-hd.mp4',
  '480p': 'funny-video-480p.mp4',
  isHD: true
}

console.log(getVideoFilepath(video))

Если мы посмотрим в браузер, то у нас вывелось funny-video-hd.mp4.

Теперь, нам еще необходимо добавить basepath к ссылке.

const getVideoFilepath = video => {
  const file = video.isHD ? video['720p'] : video['480p']
  return `/api/videos/${file}`
}

const video = {
  '720p': 'funny-video-hd.mp4',
  '480p': 'funny-video-480p.mp4',
  isHD: true
}

console.log(getVideoFilepath(video))

Все работает как нужно. Что в этом коде плохо? Запись video дублируется несколько раз и нам нужно создавать дополнительную переменную для читабельности.

Давайте попробуем написать тоже самое на Ramda, используя R.ifElse. Первым аргументом оно принимает функцию - условие, которое должно вернуть да/нет, вторым - функцию, которая выполнится если все хорошо, а третьим - функцию, если условие не выполнится.

const getVideoFilepath = R.ifElse(
  R.propEq('isHD', true),
  R.prop('720p'),
  R.prop('480p')
)

Если мы посмотрим в браузер, то нам выводится правильное название. Главная идея в том, что в каждую функцию прокидывается объект, на который вызывается ifElse. Это дает возможность делать сразу то, что нужно с этим обьектом.

В данном случае, мы проверили поле объекта на true, с помощью propEq, а потом выбрали поле с помощью R.prop. Код не содержит повторений и выглядит намного лаконичнее.

Как же нам добавить api в начало названия? Мы можем легко сделать это с помощью R.compose.

const getVideoFilepath = R.compose(
  R.concat('/api/videos/'),
  R.ifElse(
    R.propEq('isHD', true),
    R.prop('720p'),
    R.prop('480p')
  )
)

Как мы видим, код работает как и раньше, но его намного легче считывать и исправлять.

Хочу сразу заметить, что не нужно любую функцию писать на R.ifElse.

Если у нас есть три переменных, то писать R.ifElse для них не имеет особого смысла.

Например, у нас две строки и булевая переменная.

const getMessage = isWorkingTime => {
  const onlineMessage = 'We are online'
  const offlineMessage = 'We are offline'

  return isWorkingTime ? onlineMessage : offlineMessage
}

Эта функция возвращает разные строки в зависимости от того, isWorkingTime true или false.

Если мы попытаемся переписать этот код на R.ifElse, то не выйдет ничего хорошего

const getMessage = isWorkingTime => {
  const onlineMessage = 'We are online'
  const offlineMessage = 'We are offline'

  return R.ifElse(
    R.always(isWorkingTime),
    R.always(onlineMessage),
    R.always(offlineMessage)
  )()
}

Так как каждым аргументом ifElse принимает функцию, то нам нужно обернуть наши переменные в R.always, которые каждую из них превращают в функцию, которая возвращает эту переменную.

Поэтому ifElse лучше всего подходит для манипуляций с обьектом, на который он вызывается, а не для замены тернарных операторов.

Если у вас возникли какие-то вопросы или комментарии, пишите их прямо под этим видео.

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
Aleksandr Polyakh
12 месяцев назад
Доброе время суток. Подскажите пожалуйста просмотрел всю документацию Ramda.jS не смог найти как проверить сразу три значения: const num1 = 1; const num2 = 1; const num3 = 1; if(num1 && num2 && num3) 'true'; R.equals(num1, num2); // 'true Как проверить три значения? спасибо.
monsterlessons
12 месяцев назад
Добрый день. Отличный вопрос. R.all(R.equals(1), [1, 1, 2]) Еще может пригодится allPass для функций и any и anyPass с такой же логикой.