У меня полностью рабочая платформа, которая использует Rx js Behavior Subjects (Observables) в сервисах для поддержания состояния всего приложения. Он работал довольно хорошо, пока мне не понадобилось включать WebSockets для обновления информации между многими пользователями в одной учетной записи. Когда обновленная информация попадает к пользователям, я вызываю субъект поведения, чтобы проверить, должен ли быть обновлен активный поставщик (того, которого в данный момент видит пользователь), но Observable всегда возвращает «ноль», поскольку это новый экземпляр этого Наблюдаемая (а не та, которая отображается на экране пользователя).
Чтобы проверить ее, я зарегистрировал одну и ту же наблюдаемую в двух разных файлах:
// Supplier.service. ts
import { Injectable } from "@angular/core";
import { BehaviorSubject } from 'rxjs';
import { Supplier } from '../../models/supplier.model';
import { UserService } from './User.service';
@Injectable({providedIn: 'root'})
export class SupplierService {
activeSupplier = new BehaviorSubject<Supplier>(null);
constructor (
private http: HttpClient,
private userService: UserService,
) {}
{...}
getOneSupplier(supplierId: string) {
this.http.get<Supplier>(`${BASEURL}supplier/${supplierId}`)
.subscribe(supplier => {
this.activeSupplier.next(supplier);
this.activeSupplier.pipe(take(1)).subscribe(activeSupplier => {
console.log('updater:', activeSupplier); // <----------------- here
});
});
}
updateSupplierList(changedSupplier) {
this.activeSupplier.pipe(take(1)).subscribe(activeSupplier => {
console.log('Socket changing active supplier:', activeSupplier);
if (activeSupplier._id === changedSupplier._id) {
this.getOneSupplier(activeSupplier._id);
}
});
}
{...}
}
// Socket.service. js
import { Injectable } from '@angular/core';
import io from './SocketCopier.js';
import { UserService } from './User.service.js';
import { SupplierService } from './Supplier.service.js';
@Injectable({
providedIn: 'root',
})
export class SocketService {
socket;
subs = {};
constructor(
private userService: UserService,
private supplierService: SupplierService
) {
this.supplierService.activeSupplier.subscribe(activeSupplier => {
console.log('socket:', activeSupplier); // <----------------- and here
});
}
loadSocket(user) {
io.then((result) => {
if (this.socket) {
this.socket.close();
}
this.socket = result('http://localhost:3000');
this.socket.on('connect', () => {
this.socket.emit('login', { account: user.account._id })
});
this.socket.on('logged', (msg) => {
console.log(msg.text);
});
this.socket.on('supplierChange', (msg) => {
this.supplierService.updateSupplierList(msg.data);
});
});
}
}
// supplier-info.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { SupplierService } from 'src/app/shared/services/Supplier.service';
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
import { Supplier } from 'src/app/models/supplier.model';
import { filter } from 'rxjs/operators';
@Component({
selector: 'app-supplier-info',
templateUrl: './supplier-info.component.html',
styleUrls: ['./supplier-info.component.css'],
})
export class SupplierInfoComponent implements OnInit, OnDestroy {
supplier: Supplier;
subs = {};
activeRoute: string = 'projetos';
constructor(
private supplierService: SupplierService,
private route: ActivatedRoute,
private router: Router,
) { }
ngOnInit() {
this.supplierService.getOneSupplier(this.route.snapshot.params.supplierId);
}
{...}
}
Код сначала вызывает Socket.service.ts, который вызывает Supplier.service.ts, который создает субъект поведения «activeSupplier» с «нулем» в качестве начального значения.
Затем Socket.service.ts в своем конструкторе подписывается на наблюдаемую «activeSupplier» и возвращает «null», как и ожидалось.
Затем генерируется supplier-info.component.ts и в ngOnInit требуется для информации о поставщике, вызывая «this.supplierService.getOneSupplier ()». Это обновляет «активныйSupplier» BehaviorSubject, который регистрирует поставщика.
Вот результат, который я получаю из этих журналов:
socket: null
updater: {socialMediaUrls: {…}, photoUrl: "", emails: Array(0), skills: Array(0), tags: Array(4), …}
Наблюдаемое сокета никогда не обновляется, так как это новый экземпляр "supplierService", и он не использует тот же "activeSupplier" с supplier-info.component.ts. Это должно быть обновлено, верно? Как подписан на тот же Observable (хотя бы теоретически).
Что я здесь не вижу? Заранее благодарим за вашу помощь!
edit: Стоит сказать, что любая новая подписка на подписку "activeSupplier" Observable возвращает значение "ноль" в качестве первого значения (даже после второго console.log с поставщиком). ).