Является ли map () оператором? Или оператор возвращает значение map ()?
Текущая реализация map()
выглядит так:
export function map<T, R>(project: (value: T, index: number) => R, thisArg?: any): OperatorFunction<T, R> {
return function mapOperation(source: Observable<T>): Observable<R> {
if (typeof project !== 'function') {
throw new TypeError('argument is not a function. Are you looking for `mapTo()`?');
}
return source.lift(new MapOperator(project, thisArg));
};
}
Итак, map()
- это функция. Это оператор в терминах Rx JS, да, но это все еще обычная функция JavaScript. Вот и все.
Этот оператор получает project
ионную функцию обратного вызова, которая вызывается оператором map
. Этот обратный вызов является чем-то, что вы передаете map()
, например value => value.id
из этого примера:
source$.pipe(map(value => value.id))
Возвращаемое значение map
также является функцией (объявленной как OperatorFunction<T, R>
). Вы можете сказать, что это функция, поскольку map
return
s function mapOperation()
.
Теперь функция mapOperation
получает только один параметр: source
, который имеет тип Observable<T>
, и возвращает другой (преобразовано) Observable<R>
.
Подводя итог, можно сказать:
Трубный оператор - это функция, которая принимает в качестве входных данных наблюдаемое и возвращает другое наблюдаемое.
Это означает, что оператор Rx JS (который является функцией) является конвейерным, когда он принимает Observable в качестве входных данных и возвращает другой Observable , который в нашем случае имеет значение true: a * Оператор 1044 * действительно возвращает функцию (mapOperation
), чья сигнатура ((source: Observable<T>): Observable<R>
) точно указывает на это: она берет одну наблюдаемую и возвращает другую.
Оператор - это функция, которая принимает одну наблюдаемую ( источник) в качестве первого аргумента и возвращает другую наблюдаемую (конечную или внешнюю наблюдаемую)
Я уже упоминал пару раз, что оператор является просто функцией.
Ope rators принимают параметры конфигурации и возвращают функцию, которая принимает наблюдаемый источник.
Да, в этом случае оператор map()
может быть вызван, поскольку он получает параметр конфигурации - project
функция обратного вызова. Таким образом, здесь действительно нет конфликтов, так как многие операторы настраиваются.
Я бы сказал, что в этом конфликте есть:
Операторы всегда должны возвращать Observable [..] Если Вы создаете метод, который возвращает что-то отличное от Observable, это не оператор, и это нормально.
Я думаю, что это старое определение, когда конвейерные операторы не были конвейерными. До того, как были введены конвейерные операторы (я думаю, в версии 5 Rx JS), операторы возвращали Observables. Старая реализация map()
указывает именно на это.
Для получения дополнительной информации о том, почему создатели Rx JS решили ввести конвейерные операторы, ознакомьтесь с этим документом .
Еще одна замечательная статья о том, что такое наблюдаемые, можно найти здесь .
Также:
Операторы создания - другой вид оператора, который может быть вызван как отдельная функция для создания нового Observable.
of()
- пример оператора создания, который возвращает (создает) Observable. Пожалуйста, взгляните на исходный код.
TL; DR : map()
- это функция, которая обычно имеет один параметр (функция обратного вызова проекции), которая также возвращает функцию, которая получает Наблюдаемый источник и возвращает наблюдаемое назначение.
РЕДАКТИРОВАТЬ : Чтобы ответить на ваш вопрос из комментариев, я хотел бы сделать это здесь.
Да, в Rx JS 6 вы можете создать функцию, которая принимает наблюдаемую и возвращает другую, которая будет оператором. Например,
function myOperatorFunction(s: Observable<any>) {
return of(typeof s);
}
, и вы бы назвали это как
source$.pipe(myOperatorFunction);
Обратите внимание, что я не позвонил myOperatorFunction
в pipe()
, я просто ссылку на него пропустил, т.е. я не писал myOperatorFunction
с круглыми скобками, но без них. Это потому, что pipe
получает функции.
В случаях, когда вам нужно передать некоторые данные или функции обратного вызова, как в примере map
, вам понадобится другая функция, которая будет принимать ваши параметры, точно так же, как map
получает project
параметр ion, и используйте его так, как вам нравится.
Теперь вы можете задаться вопросом, почему существуют операторы, которые не получают никаких данных, но по-прежнему создаются как функции, возвращающие функцию, например refCount()
. Это должно совпадать с другими операторами, которые в основном имеют некоторые параметры, поэтому вам не нужно запоминать, какие из них не получают параметры или какие имеют параметры по умолчанию (например, min()
). В случае refCount
, если он был написан немного иначе, чем сейчас, вы могли бы написать
source$.pipe(refCountOperatorFunction);
вместо
source$.pipe(refCount());
, но вы должны знать, что Вы должны написать это таким образом, так что именно поэтому функции используются для возврата функций (которые получают наблюдаемые и возвращают другие наблюдаемые).
РЕДАКТИРОВАТЬ 2 : Теперь, когда вы знаете, что встроенные операторы возвращают функции, вы можете вызывать их, передавая наблюдаемый источник. Например,
map(value => value.toString())(of())
Но это некрасивый и не рекомендуемый способ передачи операторов, хотя он все равно будет работать. Давайте посмотрим на это в действии:
of(1, 2, true, false, {a: 'b'})
.pipe(
map(value => value.toString()),
filter(value => value.endsWith('e'))
).subscribe(value => console.log(value));
также можно записать так:
filter((value: string) => value.endsWith('e'))(map(value => value.toString())(of(1, 2, true, false, {a: 'b'})))
.subscribe(a => console.log(a));
Хотя это полностью допустимый код Rx JS, вы никак не можете придумать что он делает, когда вы читаете последний пример. На самом деле pipe
здесь делает то, что уменьшает на все функции, которые были переданы, и вызывает их, передавая предыдущий источник Observable текущей функции.