Что случилось с Observable.transduce в RxJS v5 +?

RxJS v4 раньше имел Observable.transduce метод, который принимал преобразователь. Это позволило использовать операторы преобразователей, не зависящие от библиотеки, что в прошлом имело значительные преимущества в производительности.

Источники

В RxJS v5.5 и v6 есть конвейерные операторы, а в v6 удалена цепочка методов. Из-за этого я предположил, что операторы RxJS были стандартными преобразователями. Просматривая исходный код, похоже, что это не так.

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

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

.pipe единогласно с .transduce или этот метод был полностью удален в RxJS v5?


person Kevin Ghadyani    schedule 23.11.2018    source источник


Ответы (1)


У меня был точно такой же вопрос, и я нигде не мог найти ответа. Да, вы можете pipe, но я считаю, что это создаст промежуточные наблюдаемые для каждого оператора. Хотя я не знаю наверняка, речь идет о чтении кода.

Так что я придумал свой собственный transduce оператор:

function transformForObserver(o) {
  return {
    "@@transducer/init": function() {
      return o;
    },
    "@@transducer/step": function(obs, input) {
      return obs.next(input);
    },
    "@@transducer/result": function(obs) {
      return obs.complete();
    }
  };
}

    const transduce = (obs, transducer) => {
      const xform = transducer(transformForObserver);

      return Observable.create(o => {
        return obs.subscribe({
          next: x => {
            const res = tryCatch(
              xform["@@transducer/step"],
              err => {
                console.error(`Error occurred in transducer/step!`, err);
                return err;
              }
            )(xform, o, x);

            if (res instanceof Error) { o.error(res); }
          },
          error: err => {
            console.error(`Error occurred in observable passed to Rx transduce fn!`, err);
            o.error(err);
          },
          complete: () => {o.complete();}
        });
      });
    }

Еще не тестировал, скоро напишу об этом, если будет интерес.

Обновление: я разветвил библиотеку tranducers jslongser и включил в нее такие преобразователи. Форк - это https://github.com/brucou/transducers.js, а функция transduceLazyObservable. Ср. тесты для примера использования.

person user3743222    schedule 31.12.2018
comment
Было бы неплохо расширить совместимость с другими библиотеками преобразователей. - person Kevin Ghadyani; 31.12.2018
comment
Не понимаю, что ты имеешь в виду. Это соответствует протоколу преобразователя, если это то, что вы имели в виду. - person user3743222; 31.12.2018
comment
да. Так что это позволит использовать вместе с ним и другие библиотеки! - person Kevin Ghadyani; 31.12.2018
comment
из любопытства, насколько хороши были преимущества в производительности? Преобразователи, доступные для javascript, довольно ограничены. Я, например, искал startWith и пишу его. - person user3743222; 31.12.2018
comment
Я написал эту статью о RxJS поверх стандартной обработки массивов: itnext.io/speed-up -javascript-array-processing-8d601c57bb0d. Прирост производительности был огромным на больших наборах данных. Я хотел бы увидеть, как выставляется стандартная библиотека преобразователей, поскольку у них, вероятно, меньше накладных расходов. - person Kevin Ghadyani; 31.12.2018
comment
протестировал наблюдаемый преобразователь и добавил в библиотеку. Вы можете посмотреть. С помощью этой функции вы сможете поместить ее в прототип или использовать как есть. Пометьте репозиторий, в котором он работает, и оставьте там проблему, если это не так. Тестировал только локально. - person user3743222; 01.01.2019