【发布时间】:2020-07-03 07:17:06
【问题描述】:
我有一个完整的工作平台,它在服务中使用 Rxjs 行为主体(Observables)来保持整个应用程序的状态。它工作得很好,直到我需要包含 WebSockets 来更新同一帐户中许多用户的信息。 当更新的信息到达用户时,我调用行为主题来检查是否应该更新活动的供应商(用户当前看到的供应商),但是 Observable 总是返回“null”,因为它是一个新的实例可观察的(与用户屏幕上显示的不同)。
为了测试它,我在两个不同的文件中记录了相同的 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”,初始值为“null”。
然后 Socket.service.ts 在其构造函数中订阅“activeSupplier” observable 并按预期返回“null”。
然后生成supplier-info.component.ts,在ngOnInit中它需要供应商信息,调用“this.supplierService.getOneSupplier()”。这会更新记录供应商的“activeSupplier”BehaviorSubject。
这是我从这些日志中得到的结果:
socket: null
updater: {socialMediaUrls: {…}, photoUrl: "", emails: Array(0), skills: Array(0), tags: Array(4), …}
Socket 的 observable 永远不会再次更新,因为它是“supplierService”的一个新实例,并且它不与supplier-info.component.ts 共享同一个“activeSupplier”。应该更新了吧?因为它订阅了同一个 Observable(至少理论上如此)。
我在这里没有看到什么? 提前感谢您的所有帮助!
编辑: 值得一提的是,任何对“activeSupplier” Observable 订阅的新订阅都会返回“null”,因为它是第一个值(即使在第二个带有供应商的 console.log 之后)。
【问题讨论】:
-
我明白了,您已经在根目录中注入了服务,您是否有可能在功能模块中提供服务?因为这可能会导致为该模块下的组件创建该服务的单独实例。
-
由于我对 Angular 还是很陌生,我只有一个模块 (app.module.ts) 并且它没有提供任何服务——顺便检查一下。文件中甚至没有对它们的引用。所有服务都通过“@Injectable({providedIn: 'root'})”提供。我还应该去哪里寻找?也许我只是不知道这个“在功能模块中提供服务”可能在哪里。
-
请参阅此文档angular.io/guide/singleton-services。您的服务实例创建和单例服务范围取决于您提供服务的方式。
-
@PushpikaWan 我已经检查了这个文档,这就是我在我的代码中所遵循的。我所有的服务都是在他们自己的文件中提供的,带有“@Injectable({providedIn: 'root'})”,并且在其他任何地方都没有提供。我刚刚检查了整个项目文件夹中的 Visual Studio Code 搜索,并且在它自己的文件之外没有提供任何内容(对于'root'):(
-
updateSupplierList在做什么?貌似updateSupplierList是socket接收消息时调用的方法。
标签: angular rxjs observable angular-services behaviorsubject