我发现使用 Angular 18 SSR 尝试控制来自 grapqhl-apollo 的错误响应时出现错误,服务器方法在 30 秒后返回错误,并且从带有可观察的 Angular 客户端返回错误,当我收到错误响应时,我必须仅显示加载或错误警报,但组件未渲染,30 秒后显示错误“页面/未在 30 秒内渲染”。
成分:
@Component({
selector: 'app-shop',
standalone: true,
imports: [SidebarMenuComponent, ProductCardComponent, ProductCardSkeletonComponent],
templateUrl: './shop.component.html',
styleUrl: './shop.component.css'
})
export default class ShopComponent implements OnInit{
//...
public productsPaginatedResp = signal<ProductPaginatedResponse>({
loading: true,
products: [],
error: false,
hasNextPage: false,
hasPreviousPage: false,
totalCount: 0
});
ngOnInit(): void {
//se suscribe a los cambios en la url
this.route.queryParams.subscribe(params => {
if (!this.isNavigating) {
const after = params['after'] ? atob(params['after']) : null;
const before = params['before'] ? atob(params['before']) : null;
this.updateProductsPaginated(after, before, false);
} else {
this.isNavigating = false;
}
});
}
updateProductsPaginated(after: string | null = null, before: string | null = null,
updateUrl: boolean = true) {
this.productsPaginatedResp.update(prev => ({
...prev,
loading: true,
error: false
}));
let observable$;
if (after) {
observable$ = this.productsService.getProductsPaginatedAfter(this.defaultItemsShow, after);
} else if (before) {
observable$ = this.productsService.getProductsPaginatedBefore(this.defaultItemsShow, before);
} else {
observable$ = this.productsService.getProductsPaginatedAfter(this.defaultItemsShow, null);
}
observable$.subscribe(
(response: ProductPaginatedResponse) => {
console.log(response, "resp");
if (response.error) {
this.showErrorMessage('An error occurred while fetching products');
this.productsPaginatedResp.update(prev => ({
...prev,
loading: false,
error: true,
products: []
}));
} else {
this.productsPaginatedResp.set(response);
// Evitar recarga infinita
if (updateUrl) {
this.updateUrlParams(before, after);
}
}
},
(error: any) => {
console.error('Subscription error:', error);
// Manejar cualquier error inesperado en la suscripción
this.showErrorMessage('An unexpected error occurred');
this.productsPaginatedResp.update(prev => ({
...prev,
loading: false,
error: true,
products: []
}));
}
);
}
//...
服务:
export class ProductsService {
private apollo = inject(Apollo);
getProductsPaginatedAfter(quantity: number, after: string | null): Observable<ProductPaginatedResponse> {
return this.apollo.watchQuery({
query: GET_AFTER_PRODUCTS,
variables: { first: quantity, after: after }
}).valueChanges.pipe(
map(({ data, errors }: any) => {
if (errors && errors.length) {
throw new Error(errors.map((err: any) => err.message).join(', '));
}
return {
loading: false,
products: data.productsPaginated?.nodes || [],
hasNextPage: data.productsPaginated?.pageInfo.hasNextPage || false,
hasPreviousPage: data.productsPaginated?.pageInfo.hasPreviousPage || false,
startCursor: data.productsPaginated?.pageInfo.startCursor,
endCursor: data.productsPaginated?.pageInfo.endCursor,
totalCount: data.productsPaginated?.totalCount || 0,
error: false
} as ProductPaginatedResponse;
}),
catchError(error => {
console.error('Holi GraphQL error:', error.message);
return of({
loading: false,
products: [],
hasNextPage: false,
hasPreviousPage: false,
startCursor: undefined,
endCursor: undefined,
totalCount: 0,
error: true
} as ProductPaginatedResponse);
})
);
}
}
Apollo 可能会因为开放的 websocket(或持久的 setTimeout/setInterval)而导致应用程序不稳定。
要解决此问题,您必须在角度区域之外运行函数
ngZone.runOutsideAngular() => { ... }