У меня есть приложение 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](https://spectrum.imgix.net/threads/draft/557e3580-08c4-42a5-b579-96ddb12edbf5-Screen%2520Shot%25202020-01-07%2520at%25209.49.58%2520PM.png?expires=1577664000000&ixlib=js-1.4.1&s=09127f2eb5459d60b1a332eca578ad6e)
... но когда я удаляю наблюдаемую 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), что мне нужно.