#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
на самом деле это просто удобство для конкретного сценария сопоставления, где:
- Вывод не зависит от эмиссии из наблюдаемого источника
- Вывод всегда будет одним и тем же статическим значением
Важно отметить второй момент, потому что, если целевое значение изменяется со временем, в выходных данных будут различия между 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
Комментарии:
1.
outcomeFn()
равнозначно значению0
, я считаю, что это никогда не вопрос.2. Он начинается с
0
, но меняется каждую секунду. Пример был просто для того, чтобы показать, что между ними могут быть различия. Вот StackBlitz , который демонстрирует это поведение.3. Вам лучше просто назвать это
source.pipe(mapTo(0));
, я полагаю, OP никогда не подвергает сомнению это.4. чтобы быть более понятным, OP не путает результат лямбды и функции. (он же лямбда-оператор
a => outcomeFn()
и вызов функцииoutcomeFn()
)5. кстати, первое утверждение можно упростить до
source.pipe(map(outcomeFn))