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