Observable 永远不会在 Resolver 中完成
Observable never completes in Resolver
我正在尝试实施解析器,以便在加载组件之前解析我的 API 数据。从我服务中的 HTTP 请求返回的可观察对象永远不会完成,导致路由挂起。我已经搜索了教程和 Angular 文档以了解我做错了什么。有任何想法吗?我已经概括了一些代码(只是一些命名)但不应该影响它的工作方式。
这是我的解析器服务:
@Injectable({
providedIn: 'root',
})
export class PageResolverService implements Resolve<any> {
constructor(
private service: MyAPIService,
private http: HttpClient
) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any> | Promise<any> | any {
return this.service.getPage(route.url[0].path);
}
}
这是我的路由模块(它不是 app-routing.module.ts
,而是一个“子”):
const routes: Routes = [
{
path: 'my-path',
component: MyComponent,
resolve: {
page: ResolverService,
},
},
{
path: '',
component: OtherComponent,
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
providers: [ResolverService],
})
export class RoutingModule {}
我的服务:
@Injectable({
providedIn: 'root',
})
export class MyAPIService {
constructor(private http: HttpClient) {}
public getPage = (slug: string): Observable<Page[]> => {
const uri = "https://my.com/URI"
return this.http.get<Page[]>(uri);
};
}
我的组件:
export class MyComponent implements OnInit {
page: Page = null;
constructor(
private activatedRoute: ActivatedRoute
) {
this.activatedRoute.data.subscribe((data) => {
console.log(data)
this.page = data.page[0];
});
}
ngOnInit(): void {}
}
我什至无法在我的组件构造函数中向控制台输出任何内容。如果我将解析器更改为
,我就能获取数据
return of(this.service.getPage(route.url[0].path));
并将我的组件更改为
this.activatedRoute.data.subscribe((data) => {
console.log(data);
data.page.subscribe((page) => {
this.page = page[0];
});
});
但是在我的组件完成后加载数据,我在控制台中收到无法读取的错误 property "title" of null
(page
初始化为 null)。
首先将和平移动到 ngOnInit
this.activatedRoute.data.subscribe((data) => {
console.log(data)
this.page = data.page[0];
});
去掉class中的箭头函数。
您的端点 return、页面数组或仅页面是什么?
设置正确的return类型
并添加 tap 运算符来调试你的端点
public getPage(slug: string): Observable<Page[]> {
const uri = "https://my.com/URI"
return this.http.get<Page[]>(uri).pipe(tap(console.log));
};
Angular 的 httpClient 在发出值时完成,如果你想手动完成可观察的尝试 take(1)
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any> | Promise<any> | any {
return this.service.getPage(route.url[0].path).pipe(take(1));
}
I can't even get anything output to the console in my component constructor. I am able to get data if I change my resolver to
不要做嵌套的 observables
return of(this.service.getPage(route.url[0].path));
基本上你将你的 http 请求包装在 Observable 中,然后你在组件中订阅两次,其中第二次订阅是 http 请求
this.activatedRoute.data.subscribe((data) => { // this.activatedRoute.data = of()
console.log(data);
data.page.subscribe((page) => { // data.page = this.service.getPage()
this.page = page[0]; // this subscription trigger http request
});
});
这是我找到的解决方案 -
原来这是 Angular Universal 和 SSR 的问题。只需在解析器中添加对 isPlatformBrowser(this.platformId)
的检查以生成条件 return 即可解决我的问题。
我正在尝试实施解析器,以便在加载组件之前解析我的 API 数据。从我服务中的 HTTP 请求返回的可观察对象永远不会完成,导致路由挂起。我已经搜索了教程和 Angular 文档以了解我做错了什么。有任何想法吗?我已经概括了一些代码(只是一些命名)但不应该影响它的工作方式。
这是我的解析器服务:
@Injectable({
providedIn: 'root',
})
export class PageResolverService implements Resolve<any> {
constructor(
private service: MyAPIService,
private http: HttpClient
) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any> | Promise<any> | any {
return this.service.getPage(route.url[0].path);
}
}
这是我的路由模块(它不是 app-routing.module.ts
,而是一个“子”):
const routes: Routes = [
{
path: 'my-path',
component: MyComponent,
resolve: {
page: ResolverService,
},
},
{
path: '',
component: OtherComponent,
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
providers: [ResolverService],
})
export class RoutingModule {}
我的服务:
@Injectable({
providedIn: 'root',
})
export class MyAPIService {
constructor(private http: HttpClient) {}
public getPage = (slug: string): Observable<Page[]> => {
const uri = "https://my.com/URI"
return this.http.get<Page[]>(uri);
};
}
我的组件:
export class MyComponent implements OnInit {
page: Page = null;
constructor(
private activatedRoute: ActivatedRoute
) {
this.activatedRoute.data.subscribe((data) => {
console.log(data)
this.page = data.page[0];
});
}
ngOnInit(): void {}
}
我什至无法在我的组件构造函数中向控制台输出任何内容。如果我将解析器更改为
,我就能获取数据return of(this.service.getPage(route.url[0].path));
并将我的组件更改为
this.activatedRoute.data.subscribe((data) => {
console.log(data);
data.page.subscribe((page) => {
this.page = page[0];
});
});
但是在我的组件完成后加载数据,我在控制台中收到无法读取的错误 property "title" of null
(page
初始化为 null)。
首先将和平移动到 ngOnInit
this.activatedRoute.data.subscribe((data) => {
console.log(data)
this.page = data.page[0];
});
去掉class中的箭头函数。
您的端点 return、页面数组或仅页面是什么?
设置正确的return类型 并添加 tap 运算符来调试你的端点
public getPage(slug: string): Observable<Page[]> {
const uri = "https://my.com/URI"
return this.http.get<Page[]>(uri).pipe(tap(console.log));
};
Angular 的 httpClient 在发出值时完成,如果你想手动完成可观察的尝试 take(1)
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any> | Promise<any> | any {
return this.service.getPage(route.url[0].path).pipe(take(1));
}
I can't even get anything output to the console in my component constructor. I am able to get data if I change my resolver to
不要做嵌套的 observables
return of(this.service.getPage(route.url[0].path));
基本上你将你的 http 请求包装在 Observable 中,然后你在组件中订阅两次,其中第二次订阅是 http 请求
this.activatedRoute.data.subscribe((data) => { // this.activatedRoute.data = of()
console.log(data);
data.page.subscribe((page) => { // data.page = this.service.getPage()
this.page = page[0]; // this subscription trigger http request
});
});
这是我找到的解决方案 -
原来这是 Angular Universal 和 SSR 的问题。只需在解析器中添加对 isPlatformBrowser(this.platformId)
的检查以生成条件 return 即可解决我的问题。