В чем смысл mapTo в RxJS?

#javascript #typescript #rxjs

#javascript #typescript #rxjs

Вопрос:

Я читаю документы для mapTo и я просто не понимаю смысла существования этого оператора. Я понимаю, что он делает, но две строки ниже должны привести к эквивалентному результату.

 const outcome = "bzzz";
const result1 = source.map(a => outcome);
const result2 = source.mapTo(outcome);
 

Тем не менее, создатели RxJS решили увеличить сложность, добавив дополнительный метод. Это кажется бессмысленным как таковое, поэтому я подозреваю, что в этом есть нечто большее, чем кажется на первый взгляд.

Какой смысл иметь выделенный оператор для такого конкретного случая?

Комментарии:

1. В этом нет ничего большего, чем кажется на первый взгляд; это просто сокращение. Что касается того, почему вы должны спросить их.

2. @DaveNewton Это сюрприз. Там нет упоминания о его статусе как метода удобства или сокращения, поэтому, естественно, я предположил, что в этом есть какая-то магия, например, производительность или что-то в этом роде. Но, учитывая ваш комментарий, это немного разочаровывает. 🙂

3. Безусловно, есть некоторые возможности оптимизации, когда вы знаете, что вы сопоставляете с постоянным значением. Я не могу сказать, реализованы ли они на самом деле или даже запланированы. Вы сами посмотрели на реализацию?

4. github.com/ReactiveX/rxjs/blob/master/src/internal/operators /… источник] подводит итог; Я имею в виду, технически я полагаю, что это немного быстрее, поскольку это не увеличивает индекс: shrug: github.com/ReactiveX/rxjs/blob/master/src/internal/operators /…

5. Функция in map выполняется при каждом выделении значения, в то время mapTo как аргумент вычисляется один раз при создании оператора.

Ответ №1:

Различия между map и mapTo

На первый взгляд, мы видим, что map он принимает функцию обратного вызова

 function map<T, R>(project: (value: T, index: number) => R, thisArg?: any)
 

принимая mapTo во внимание, что принимает статическое значение

 function mapTo<R>(value: R)
 

Итак, явное различие заключается в том, что map функция обратного вызова может генерировать значение в зависимости от предоставленных аргументов. Это не тот случай mapTo , когда вы просто предоставляете значение, которое всегда будет передаваться следующему подписчику в цепочке. Если хотите, mapTo(value) можно использовать как

 map(() => value)
 

Мы также можем вывести это из исходного кода:

 // `mapTo`
() => subscriber.next(value)

// `map`; `project` is the provided callback function
() => subscriber.next(project.call(thisArg, value, index  ));
 

Но вы можете не захотеть этого делать, зачем вызывать функцию, когда вы можете напрямую использовать значение?

Некоторые варианты использования

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

 createEffect(
  () => this.actions.pipe(
    /* some logic here... */
    mapTo(staticAction('a message here')),
  )
);
 

Еще один, который может показаться не очень практичным, — это когда вы хотите имитировать некоторые поступающие запросы:

 merge(
  timer(300).pipe(mapTo("req#1")),
  timer(600).pipe(mapTo("req#2")),
  timer(100).pipe(mapTo("req#3")),
  timer(900).pipe(mapTo("req#4")),
).pipe(
  /* some complicated logic here... */
)
 

В любом случае, смысл этого оператора, по крайней мере, с моей точки зрения, в том, чтобы указать, что вы хотите передавать статические значения, то есть значения, которые не зависят от данных предыдущего подписчика.

Комментарии:

1. Смехотворно хорошо объяснено и приведено в качестве примера. Спасибо, приятель. 1 оч зеленая проверка, конечно.

2. Я рад, что смог помочь!

Ответ №2:

mapTo на самом деле это просто удобство для конкретного сценария сопоставления, где:

  1. Вывод не зависит от эмиссии из наблюдаемого источника
  2. Вывод всегда будет одним и тем же статическим значением

Важно отметить второй момент, потому что, если целевое значение изменяется со временем, в выходных данных будут различия между map(a => target) и mapTo(target) :

  • map(a => outcome) — вернет текущее значение «результат» (возможно, разные результаты)
  • mapTo(outcome) — вернет первое переданное значение «результат» (один и тот же результат каждый раз)
 let outcome = 0;
// change 'outcome' every second
interval(1000).pipe(tap(n => outcome = n * 2)).subscribe();

const source = interval(1000).pipe(take(4));

source.pipe(map(a => outcome));  // 0, 2, 4, 6
source.pipe(mapTo(outcome));     // 0, 0, 0, 0
 

Демонстрация StackBlitz

Комментарии:

1. outcomeFn() равнозначно значению 0 , я считаю, что это никогда не вопрос.

2. Он начинается с 0 , но меняется каждую секунду. Пример был просто для того, чтобы показать, что между ними могут быть различия. Вот StackBlitz , который демонстрирует это поведение.

3. Вам лучше просто назвать это source.pipe(mapTo(0)); , я полагаю, OP никогда не подвергает сомнению это.

4. чтобы быть более понятным, OP не путает результат лямбды и функции. (он же лямбда-оператор a => outcomeFn() и вызов функции outcomeFn() )

5. кстати, первое утверждение можно упростить до source.pipe(map(outcomeFn))