我正在寻找一种有效的方法来检查Angular应用程序中是否已设置了变量,因此我不必继续检查其是否已设置。当用户首次请求页面时,我有一项将所有产品加载到变量中的服务。示例:
export class ProductService {
public products: Product[];
constructor(private http: HttpClient) { }
init(): any {
if (!this.products) {
this.http.get<Product[]>("https://my-api.com/GetAllProducts").subscribe(products => {
this.products = products;
});
}
}
}
然后我在productService.init()
文件中简单地说app.component.ts
来称呼它,以确保它初始化产品以备后用。但是,我也有一种方法可以从产品ID中获取产品:
getProductFromProductId(productId: string) {
return this.products.find(x => x.id === productId);
}
此getProductFromProductId
方法在每个页面上至少调用一次。假设init()
方法需要2000毫秒的加载时间,因为有很多产品,调用getProductFromProductId()
会失败,因为尚未设置products
。要解决此问题,我可以执行以下操作:
getProductFromProductId(productId: string) {
if(!this.products) {
setTimeout(() => {
console.log("Products not loaded yet");
getProductFromProductId(productId);
}, 10);
} else {
return this.products.find(x => x.id === productId);
}
}
上面的代码检查是否每10毫秒设置一次products
。如果没有,它只会再次调用该方法。
但是,让我们想象一下该服务中有10种方法。这有很多“ 尚未加载”的可能性,这意味着我将不得不重复相同的代码10次(或将其移至函数中,但您明白了)。最大的问题是getProductFromProductId
和init
都被同时调用,因此,基本上我们需要等待init
完成。
有更好的方法吗?
答案 0 :(得分:0)
您可以将产品列表更改为“可观察”。我建议一个BehaviorSubject。
import {BehaviorSubject, Observable} from 'rxjs';
export class ProductService {
public products: BehaviorSubject<Product[]> = new BehaviorSubject([]);
constructor(private http: HttpClient) { }
init(): any {
if (!this.products) {
this.http.get<Product[]>("https://my-api.com/GetAllProducts").subscribe(products => {
if(products){
this.products.next(products);
}
});
}
}
getProducts(): Observable<Product[]> {
return this.products.asObservable();
}
}
然后让您的ts文件预订BehaviorSubject。一旦满足,所有订户都会得到通知,可以做出反应。
TS文件
ngOnInit(): void {
this.productService.getProducts().subscribe( list => {
if(list) {
// fill your local list
this.productList = list;
// or call a method that processes this list
this.processProductList(list);
// or other actions
}
});
}
答案 1 :(得分:0)
由于我无法使用BehaviorSubject
(不知道为什么,但我根本无法使用它),所以我选择了常规的Subject
。这是一个示例:
product.service.ts
@Injectable()
export class ProductService {
public products = new Array<Product>();
public productsSubject: Subject<Product[]> = new Subject();
constructor(private http: HttpClient) { }
init(): any {
this.http.get<Product[]>("https://my-api.com/GetAllProducts").subscribe(products => {
this.products = products;
this.productsSubject.next(products);
});
}
getProductByProductId(productId: string): Observable<Product> {
if (this.products.length > 0)
return of(this.products.find(x => x.id === productId));
return new Observable(observer => {
this.productsSubject
.subscribe(products => {
var p = products.find(x => x.id === productId);
observer.next(p);
observer.complete();
});
});
}
}
如果要使用import { of } from 'rxjs';
,请记住在顶部添加of()
。
然后在我们的组件中,我们可以简单地做到:
random.component.ts
this.productsService.getProductByProductId(productId)
.subscribe(product => {
//do something with product
});
这确保我们的服务方法相对较小并且易于理解,而组件的代码也较小且易于理解。