Должен ли оператор rx js возвращать функцию или наблюдаемое? - PullRequest
1 голос
/ 06 февраля 2020

Меня немного смущают различные определения оператора в rx js.

Ниже я приведу некоторые определения:

1 A Pipeable Operator - это функция, которая принимает Observable в качестве входных данных, а возвращает другой Observable .
Creation Operators - это оператор другого типа, который можно вызывать как автономные функции. для создания новой наблюдаемой

2 Оператор - это функция, которая принимает одну наблюдаемую (источник) в качестве первого аргумента, а возвращает другую наблюдаемую ( назначение или внешняя наблюдаемая)

3 Операторы принимают параметры конфигурации, и возвращают функцию , которая принимает наблюдаемый источник.

4 Операторы всегда должны возвращать Observable [..] Если вы создаете метод, который возвращает что-то отличное от Observable, это не оператор , и это нормально.

Поскольку 1,2,4, похоже, конфликтуют с 3 , какое определение является правильным. Есть ли лучшее определение операторов rx js?

Например: в случае map. map() сам оператор? Или оператор возвращает значение map ()?

Ответы [ 2 ]

0 голосов
/ 06 февраля 2020

Да. Сама карта является оператором.

Каждый оператор возвращает Observable, чтобы позже вы могли подписаться на Observable, который вы создали.

Конечно, когда я говорю «вы создали», я имею в виду, что вы создали с помощью оператор создания или использование класса Observable: new Observable

Трубный оператор - это просто оператор, который будет находиться внутри служебной функции pipe.

Любая функция, которая возвращает функцию с сигнатурой Observable может быть передан по трубопроводу, и поэтому вы можете создавать свои собственные Observables и операторы конвейера.

Я почти уверен, что вы уже знаете все это, и все, что вы хотите знать, - это причина конфликта в то, что вы читаете.

Во-первых, вам не нужно ничего направлять в Observable. Вы можете создать Observable и подписаться на него, и все.

Поскольку вам не нужно ничего передавать в Observable, что мы должны делать с операторами?

Они используются только внутри a pipe?

Ответ: NO

Как уже упоминалось, в вашем примере оператор выбирает параметры конфигурации:

const squareValues = map((val: number) => val * val);

, а затем возвращает новая функция, которая берет исходный объект Observable, чтобы вы могли позже подписаться на него:

const squaredNums = squareValues(nums);

Как мы видим, карта взяла (val: number) => val * val и вернула функцию, которая теперь получает Observable nums : const nums = of(1, 2, 3);

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

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

Итак, еще раз, позади В сценах вы можете ссылаться на pipe как на более прохладный способ сделать операции с вашим источником Observable, а не объявлять множество переменных, использующих различные операторы с некоторой конфигурацией, которые возвращают функцию, которая принимает Observable для источника.

0 голосов
/ 06 февраля 2020

Является ли 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 текущей функции.

...