Observable 永远不会在解析器中完成

时间:2021-02-12 19:27:27

标签: angular observable resolver

我正在尝试实现一个解析器,以便在加载组件之前解析我的 API 数据。从我的服务中的 HTTP 请求返回的 observable 永远不会完成,导致路由挂起。我已经搜索了教程和 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 nullpage 被初始化为 null)。

2 个答案:

答案 0 :(得分:0)

首先将和平转移到ngOnInit

this.activatedRoute.data.subscribe((data) => {
        console.log(data)
        this.page = data.page[0];
    });

去掉类中的箭头函数。

您的端点返回什么,页面数组还是仅页面?

设置正确的返回类型 并添加 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 在发出值时完成,如果您想手动完成 observable,请尝试 take(1)

resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<any> | Promise<any> | any {
    return this.service.getPage(route.url[0].path).pipe(take(1));
  }
<块引用>

我什至无法在组件构造函数中向控制台输出任何内容。如果我将解析器更改为

,我可以获得数据

不要做嵌套的 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
      });
    });

答案 1 :(得分:0)

这是我找到的解决方案 - https://stackoverflow.com/a/56280405/11790081

事实证明这是 Angular Universal 和 SSR 的问题。只需添加对 isPlatformBrowser(this.platformId) 的检查以在解析器中产生条件返回就解决了我的问题。