Несвязанный наблюдаемый Rx JS вызывает многократное срабатывание подписки Apollo на ngOnInit - PullRequest
1 голос
/ 09 января 2020

У меня есть приложение musi c, которое должно загрузить альбом (я называю это отправкой) и раздел комментариев. Я столкнулся со странной проблемой: когда я создаю наблюдаемую comments$, она вызывает двойную активацию наблюдаемой submission$ при начальной загрузке страницы. Вот мой процесс отладки. Кто-нибудь может объяснить, что происходит?

Примечание: Я безуспешно разместил это в спектральном чате Apollo и добавил обновление внизу.

В моем ngOnInit() у меня есть два следующих запроса:

// to load the submission
this.submission$ = this.submissionGQL.watch({
  id: this.submissionId
}).valueChanges.pipe(
  takeUntil(this.ngUnsubscribe),
  map(submission => {
    console.log(submission)
    const sub = submission.data.submission;
    sub.releaseDate = moment.utc(moment.unix(parseInt(sub.releaseDate))).format("MMM DD, YYYY");
    sub.proof = new URL(sub.proof || "https://releasehub.co").hostname;
    return sub;
  }),
  shareReplay(1)
);

// to load all the comments for that submission
this.comments$ = this.paginatedCommentsGQL.watch(
  {
    cursor: this.cursor,
    limit: this.limit,
    submissionId: this.submissionId
  }
).valueChanges.pipe(
  takeUntil(this.ngUnsubscribe),
  tap((response) => {
    this.cursor = response.data.paginatedComments.response_metadata.next_cursor;
  }),
  map((response) => {
    return response.data.paginatedComments.comments
  })
)

Я использую эти наблюдаемые с асин c трубами в моих Angular HTML, например, так:

<ng-container *ngIf="submission$ | async as submission; else loading">
<!-- submission code here -->
</ng-container>

<app-comment *ngFor="let comment of comments$ | async" [comment]="comment"></app-comment>

Однако при загрузке страницы я заметил, что это приводит к двойному срабатыванию submission$ (я добавил консольный журнал в конвейере представления map ():

Screen Shot 2020-01-07 at 9.49.58 PM.png

... но когда я удаляю наблюдаемую comments$, все работает просто замечательно. Это привело меня к мысли, что запрос комментариев заставлял кеш обновлять то, что использует запрос submission$. Конечно, когда я пометив fetchPolicy из comments$ как no-cache, запрос не сработал дважды, но мне стало любопытно, что вызвало двойной триггер .. Оба запроса graphql возвращают некоторую информацию о пользователях, поэтому я подумал Может быть, это была проблема. Вот что возвращается из обоих запросов, Я прокомментировал разделы, которые относятся к пользователям:

Представление:

query Submission($id: Int) {
    submission(id: $id) {
        id
        artistID
        title
        artists {
            id,
            name,
            imageURL,
            artistUID
        },
        hunter {  // this is a single user
            id,
            imageURL,
            username
        },
        contributors { // this is an array of users
            id,
            imageURL,
            username
        }
    }
}

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

query PaginatedComments($cursor: String, $limit: Int, $submissionId: Int) {
    paginatedComments(cursor: $cursor, limit: $limit, submissionId: $submissionId) {
        response_metadata {
          next_cursor
        }
        comments {
            id,
            userID,
            content,
            createdAt,
            user { // single user, aka the commentor
                id,
                username,
                imageURL
            }
        }
    }
}

Итак, чтобы проверить свою теорию, я удалил user ответ от PaginatedComments, но это все же привело к повторному запуску кэша.

В моем следующем тесте я поместил запрос comments$ в setTimeout через 3 секунды после загрузки страницы. Интересно, что это не привело к повторному запуску submission$, как если бы comments$ был загружен при загрузке страницы. WEIRD.

Мой следующий эксперимент состоял в том, чтобы перенастроить результаты запроса comments$ в BehaviorSubject, например так:

commentsSubject = new BehaviorSubject([]);
comments$ = this.commentsSubject.asObservable();

this.paginatedCommentsQuery.valueChanges.pipe(
  tap((response) => {
    this.cursor = response.data.paginatedComments.response_metadata.next_cursor;
  }),
  map((response) => {
    this.commentsSubject.next(response.data.paginatedComments.comments)
  })
)

Выполнение вышеуказанного для загрузки комментариев не вызвать submission$ наблюдаемый для повторного запуска. Так странно. У кого-нибудь есть мысли по поводу того, почему начальные методы в верхней части этого поста вызывают submission$ срабатывание дважды? Я старался изо всех сил отлаживать себя, но я достиг своей границы (я думаю), насколько далеко я могу отлаживать на моей стороне. Спасибо!

Я использую apollo-angular: ^1.7.0


Обновление! Так что я вроде понимаю, почему выполнение этого в моем map() канале приведет к тому, что наблюдаемое перезапустится:

sub.releaseDate = moment.utc(moment.unix(parseInt(sub.releaseDate))).format("MMM DD, YYYY");
sub.proof = new URL(sub.proof || "https://releasehub.co").hostname;

, так как я меняю значение ... НО, почему это происходит только тогда, когда comments$ существует и при загрузке страницы? Это то, что озадачивает меня. Я все еще хотел бы знать ответ, но сейчас я выбрал лучший (?) Подход и добавил angular pipes, которые выполняют преобразования текста как для releaseDate (releaseDate | formatDate), так и proof ( доказательство | shortURL), что мне нужно.

...