路由期间服务返回的对象为空

时间:2018-03-07 10:00:07

标签: angular rxjs

我在我开发的应用程序中有一项服务,它接收我点击的项目并将它们存储在一个状态中,在我点击它们时合并新项目。我可以通过调用一个返回Observable的函数来访问这个存储状态(让我们称之为getItems)。

我还有一个方法,使用@ angular / router包导航到应用程序的不同部分,然后导航方法 - this.router.navigate(path);。重要的是,存储在服务中的上述项目随后可用于新路由中的应用程序 - 它们就是这样。但是,我现在正在尝试实现一个功能,它在导航到路径之前/之前查看项目,因为应用程序的新功能可能需要根据商店中存在的项目进行额外的HTTP请求。问题是,当我这样做时(在Resolve方法中),服务返回一个空对象。导航完成后,我再次调用该服务,它将返回正确的项目。那么为什么服务会在resolve方法中简单地返回一个空对象?以下是我的代码示例(大大简化):

export const ROUTES = [
  {
    path: '',
    component: ExampleComponent,
    children: [
      {
        path: '/child', loadChildren: './child-component/child-component.module#ChildComponentModule', resolve: {
        objSummary: ComponentResolverService
      }
    ]
  }
]

因此,当我向商店添加商品时(点击它们),我就在/。然后,我点击一个链接/按钮,将我带到/child。接下来是ComponentResolverService

@Injectable()
export class ComponentResolverService implements Resolve<ObjectType> {
  constructor(private http: HttpClient, private itemStoreService: ItemStoreService) {}

  public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<ObjectType> {
    // this method returns the result of an HTTP call. In that HTTP call, I need to get the items which have previously been stored
    let request: Observable<ObjectType>;
    this.itemStoreService.getItems().subscribe(items => {
      console.log(items); // returned as empty object {}
      request = this.http.post<ObjectType>(apiUrl, items);
    });
    return request;
  }
}

如果我向ChildComponent中的itemStoreService.getItems()发出请求,它会返回一个对象,其中包含我之前添加到商店的项目。它只是在解析器中它返回空。

最后,ItemStoreService

interface Item {
  attribute1: string;
  attribute2: string;
}

interface Store<T> {
  [key: string]: T;
}

export class ItemStoreService {

  private items: BehaviorSubject<Store<Item>> = new BehaviorSubject<Store<Item>>();
  private itemData: Store<Item>;

  public getItems(): Observable<Store<Item>> {
    return this.items.map((x: Store<Item) => _.cloneDeep(x));
  }

  public addItem(itemName: string, item: Item): void {
    this.itemData[itemName] = item;
    this.items.next(this.itemData);
  }

}

当单击某个项目时,在主要组件(在'/'中呈现)时调用addItem方法。我没有包含此代码,因为它不是问题,但包括完整性的方法。

所以基本上:getItems()返回一个带有正确项目的Observable,除了Resolver服务,它返回一个空对象,我需要它返回解析器服务中的项目,以便我可以发出HTTP请求在API上开发应用程序。

编辑:使用Chrome调试器获取更多信息:我添加了一个断点,点击链接并使用路由器:(return this.router.navigate(path);)。此处,在Chrome调试器范围面板中,itemStoreService在范围内,而BehaviorSubject变量的值包含存储的项目。所以这很好。但是,我在解析器服务中添加了一个断点,并在范围内找到了itemStoreService;此处items的值为{}。因此,在初始路由激活和路由解析之间的某处,数据将丢失,然后在呈现子组件时再次找到。我会继续添加更多的断点并进行检查,希望这能让我找到它丢失的地方。

1 个答案:

答案 0 :(得分:0)

此问题的解决方案是在core / root app.module.ts文件中导入整个应用程序中应保持相同的任何服务。我在多个NgModule声明中单独导入ItemStoreService,这意味着它是单独注入的。因此,在某些地方,items变量被重新初始化为空对象;其中一个地方在我的路由从组件到组件(但在每个组件中定义相同)。

为了答案完整性,上面的代码可以保持完全相同,我只需要在app.module.ts中确保我导入了ItemStoreService:

@NgModule({
  bootstrap: [ AppComponent ],
  declarations: [ AppComponent ],
  imports: [ ... ],
  providers: [
   ItemStoreService,
   ...
  ]
});

然后我必须确保没有在任何其他模块中导入ItemStoreService。

感谢this answer为我提供了初步解决方案。