Как три функции обратного вызова принимаются в метод subscribe как один объект?

#angular #rxjs

#angular #rxjs

Вопрос:

После того, как мы сделаем некоторые наблюдаемые

 let observable = new Observable(observer => {
      let x = 5;
      if (x == 15) {
        observer.error('something went wrong');
      } else {
        observer.next('produce some value');
      }
      observer.complete();
    });
 

существуют разные способы подписки на эти три функции обратного вызова от наблюдателя.

 observable.subscribe(
      function next(data) {
        console.log(data);
      },
      function error(err) {
        console.log(err);
      },
      function complete() {
        console.log('done');
      }
    )
 

или с помощью функций со стрелками istead с ключевым словом function

 observable.subscribe(
      x => 
      {
      console.log(x);
      },
      err => 
      {
        console.log(err);
      },
      () => 
      {
        console.log('done');
      },
 

и эти два способа работают — так что в конце в методах подписки мы заканчиваем тремя
функциями, которые получают значения от наблюдателя.

Но когда я пишу, например

 observable.subscribe({
      next: (data) => console.log(data),
      error: (err) => console.log(err),
      complete: () => console.log('done')
    })

 

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

Мой вопрос в том, как и почему это работает, когда функции «завернуты» в один объект?

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

1. Именно так и написан метод subscribe. он принимает до 3 обратных вызовов или объект, реализованный, как вы. Оба метода эквивалентны.

2. Хорошо, Квентин, спасибо за ваш отзыв. Как я могу увидеть реализацию в фоновом режиме метода subscribe ?

3. rxjs-dev.firebaseapp.com/api/index/class/Observable

4. обычно вы можете проверить определение типа в своих node_modules . В моем случае это находится в node_modules/rxjs/internal/Observable.d.ts, затем найдите «subscribe». Но если вы хотите проверить исходный код, зайдите в репозиторий github github.com/ReactiveX/rxjs/blob/master/src/internal /…

Ответ №1:

Вот реализация псевдокода subscribe

 subscribe(...args){
  let observer = {
    next: _ => {/* Do nothing */},
    error: err => { throw err },
    complete: () => {/* Do nothing */}
  }

  if(isAFunction(args[0])) observer.next = args[0];
  if(isAFunction(args[1])) observer.error = args[1];
  if(isAFunction(args[2])) observer.complete = args[2];

  if(isAnObject(args[0])){
    const partialObserver = args[0];
    if(isAFunction(partialObserver.next)) observer.next = partialObserver.next;
    if(isAFunction(partialObserver.error)) observer.error = partialObserver.error;
    if(isAFunction(partialObserver.complete)) observer.complete = partialObserver.complete;
  }

  return this._subWithObserver(observer);
}
 

Очевидно, что это не полная история, но это идея о том, как это делается. Вы можете покопаться в источнике, чтобы увидеть, как частичные наблюдатели и / или функции отображаются в соответствующие наблюдатели.

Скрывается за кулисами error и complete фактически используется для обеспечения соблюдения наблюдаемого контракта.

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

1. Спасибо Mrk. Я принял и поддержал ваш ответ. Не могли бы вы просто написать мне в комментарии или в своем ответе также ссылку из исходного кода this, который вы вставили сюда, из их документации? Я пытался найти это здесь github.com/ReactiveX/rxjs/blob/master/src/internal /… но я его не нашел.