Angular解析器没有更新或重新获取数据,尽管`runGuardsAndResolvers`设置为'always'?

Rea*_*ues 7 angular-routing angular angular-resolver

我有一组Angular路由,带有实体列表,有两条子路由,用于创建这样的实体和编辑现有实体.实体列表resolver附加了它以在显示组件之前预取组件的数据.这些路由可以总结如下,进一步了解如何在代码中描述这些路由.

  • 指数: /items
  • 创建: /items/create
  • 编辑: /items/:itemId/edit

但是,如果我在/items/create,并成功创建一个项目,导航"返回" /items或任何编辑路线,甚至返回到/将不会导致我的解析器获取像我期望的更新数据.尽管将runGuardsAndResolvers属性设置为"始终".我的理解是这个属性应该能够实现我正在寻找的功能.

为什么会这样,我怎样才能启用我正在寻找的功能,而不需要在我的组件中订阅路由器事件和复制逻辑.

路线

const itemRoutes: Routes = [
    {
        path: '', // nb: this is a lazily loaded module that is itself a child of a parent, the _actual_ path for this is `/items`. 
        runGuardsAndResolvers: 'always',
        component: ItemsComponent,
        data: {
            breadcrumb: 'Items'
        },
        resolve: {
            items: ItemsResolver
        },
        children: [
            {
                path: 'create',
                component: CreateItemComponent,
                data: {
                    breadcrumb: 'Create Item'
                }
            },
            {
                path: ':itemId/edit',
                component: EditOrArchiveItemComponent,
                data: {
                    breadcrumb: 'Editing Item :item.name'
                },
                resolve: {
                    item: ItemResolver
                }
            }
        ]
    }
];
Run Code Online (Sandbox Code Playgroud)

ItemsResolver

@Injectable()
export class ItemsResolver implements Resolve<ItemInIndex[]> {
    public constructor(public itemsHttpService: ItemsHttpService, private router: Router) {}

    public resolve(ars: ActivatedRouteSnapshot, rss: RouterStateSnapshot): Observable<ItemInIndex[]> {
        return this.itemsHttpService.index().take(1).map(items => {
            if (items) {
                return items;
            } else {
                this.router.navigate(['/']);
                return null;
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

ItemsHttpService

(根据要求发布)

@Injectable()
export class ItemsHttpService  {

    public constructor(private apollo: Apollo) {}

    public index(): Observable<ItemInIndex[]> {
        const itemsQuery = gql`
            query ItemsQuery {
                items {
                    id,
                    name
                }
            }
            `;

        return this.apollo.query<any>({
            query: itemsQuery
        }).pipe(
            map(result => result.data.items)
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

Spl*_*lex 10

首先.

不是你应该如何使用Resolver.

Resolver只有在您的路径必不可少的情况下才应使用所需数据.因此,当您拥有专用数据路径并且希望在继续加载组件之前确保此数据存在时,解析器才有意义.

让我们以您的项目应用程序为例,从用户的角度来看待问题.

/项目

用户导航到/items他将要看到的内容并不是什么.这是因为解析器在用户可以到达组件之前获取所有项目.只有在解析器从api中获取所有项目后,才会将用户委派给ItemsComponent.

但这不是必要的和糟糕的用户体验.

为什么不直接委托用户ItemsComponent.如果你有一个很棒的桌子,有很多按钮和花哨的酷css,你可以给你的应用程序时间来呈现这些元素,同时Service从api获取数据.要指示数据正在加载的用户,您可以在表中显示一个很好的progress-spinner(-bar),直到数据到达为止.

/项目/创建

同样在这里.用户必须等到Resolver从api获取所有数据才能到达CreateComponent.应该清楚的是,只有用户可以创建项目才能获取所有项目.所以没有必要Resolver

/项目/:的itemId /编辑

这是解析器的最佳位置.当且仅当项目存在时,用户才能够路由到此组件.但是,当您定义一个解析器以在其中一个子路由被激活时获取所有项目时,用户将面临与先前路由相同的错误用户体验.

从路由中删除ItemsResolver.

const routes: Routes = [
  {
      path: '',
      component: ItemsComponent,
      children: [
        {
          path: '',
          component: ItemsListComponent,
          data: {
            breadcrumb: 'Items'
          },
        },
        {
          path: 'create',
          component: CreateItemComponent,
          data: {
            breadcrumb: 'Create Item'
          },
        },
        {
          path: ':itemId/edit',
          component: EditOrArchiveItemComponent,
          data: {
            breadcrumb: 'Editing Item :item.name'
          },
          resolve: {
            item: ItemResolverService
          }
        }
      ]
  }
];
Run Code Online (Sandbox Code Playgroud)

您可以在ItemsService其中定义一个BehaviorSubject,它将您最后提取的项目保存为缓存.每当一个用户路由从后创建编辑ItemsComponent您的应用程序可以立即呈现缓存的项目,在此期间您的服务可以同步在后台的项目.

我实现了一个小工作示例App:https: //stackblitz.com/github/SplitterAlex/stackoverflow-48640721

结论

A Resolver只在编辑项目路线上有意义.

Resolver谨慎使用!

  • 我不知道这如何回答关于将选项runGuardsAndResolvers设置为“ always”的情况下不刷新已解析数据的问题的任何问题... (7认同)