sha*_*non 70 promise observable dependency-resolver angular
在Angular 1.x中,UI-Router是我的主要工具.通过返回"解析"值的承诺,路由器将在呈现指令之前等待承诺完成.
或者,在Angular 1.x中,null对象不会使模板崩溃 - 所以如果我不介意暂时不完整的渲染,我可以$digest在promise.then()填充最初为空的模型对象后使用它进行渲染.
在这两种方法中,如果可能的话,我宁愿等待加载视图,如果无法加载资源,则取消路由导航.这为我节省了"取消导航"的工作.编辑:注意这具体意味着这个问题要求Angular 2期货兼容或最佳实践方法来执行此操作,并要求尽可能避免使用"Elvis操作符"!因此,我没有选择那个答案.
但是,这两种方法都不适用于Angular 2.0.当然,有一个标准的解决方案计划或可用于此.有谁知道它是什么?
@Component() {
template: '{{cats.captchans.funniest}}'
}
export class CatsComponent {
public cats: CatsModel;
ngOnInit () {
this._http.get('/api/v1/cats').subscribe(response => cats = response.json());
}
}
Run Code Online (Sandbox Code Playgroud)
以下问题可能反映了相同的问题:加载数据PROMISE后的Angular 2渲染模板.请注意,问题中没有代码或接受的答案.
teh*_*ron 84
试试{{model?.person.name}}这个应该等待模型不是undefined然后渲染.
Angular 2将此?.语法称为Elvis运算符.在文档中引用它很难找到,所以这里是它的副本,以防它们更改/移动它:
Elvis运算符(?.)和null属性路径
Angular"Elvis"运算符(?.)是一种流畅且方便的方法,可以防止属性路径中的null和undefined值.如果currentHero为null,则保护视图呈现失败.
The current hero's name is {{currentHero?.firstName}}让我们详细说明问题和这个特定的解决方案.
当以下数据绑定title属性为null时会发生什么?
The title is {{ title }}视图仍然呈现但显示的值为空白; 我们只看到"标题是",之后什么都没有.这是合理的行为.至少应用程序不会崩溃.
假设模板表达式涉及属性路径,如下一个示例所示,其中我们显示空英雄的firstName.
The null hero's name is {{nullHero.firstName}}JavaScript抛出空引用错误,Angular也是如此:
TypeError: Cannot read property 'firstName' of null in [null]更糟糕的是,整个观点都消失了.
如果我们认为英雄财产绝不能为空,我们可以声称这是合理的行为.如果它必须永远不是null而且它是null,那么我们已经编写了一个应该被捕获并修复的编程错误.抛出异常是正确的做法.
另一方面,属性路径中的空值可能不时,特别是当我们知道数据最终到达时.
在我们等待数据的同时,视图应该在没有投诉的情况下呈现,并且null属性路径应该像title属性一样显示为空白.
不幸的是,当currentHero为null时,我们的应用程序崩溃了.
我们可以用NgIf来解决这个问题
<!--No hero, div not displayed, no error --><div *ngIf="nullHero">The null hero's name is {{nullHero.firstName}}</div>或者我们可以尝试使用&&链接属性路径的一部分,因为知道表达式在遇到第一个null时会失效.
The null hero's name is {{nullHero && nullHero.firstName}}这些方法具有优点,但它们可能很麻烦,尤其是在属性路径很长的情况下.想象一下,在诸如abcd之类的长属性路径中的某处保护null
Angular"Elvis"运算符(?.)是一种更流畅,更方便的方法来防范属性路径中的空值.当它达到第一个空值时,表达式会失效.显示为空白但应用程序不断滚动且没有错误.
<!-- No hero, no problem! -->The null hero's name is {{nullHero?.firstName}}它也适用于长属性路径:
a?.b?.c?.d
Tet*_*Dev 35
该套餐@angular/router具有Resolve路线的属性.因此,您可以在渲染路径视图之前轻松解析数据.
请参阅:https://angular.io/docs/ts/latest/api/router/index/Resolve-interface.html
截至2017年8月28日的文档示例:
class Backend {
fetchTeam(id: string) {
return 'someTeam';
}
}
@Injectable()
class TeamResolver implements Resolve<Team> {
constructor(private backend: Backend) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<any>|Promise<any>|any {
return this.backend.fetchTeam(route.params.id);
}
}
@NgModule({
imports: [
RouterModule.forRoot([
{
path: 'team/:id',
component: TeamCmp,
resolve: {
team: TeamResolver
}
}
])
],
providers: [TeamResolver]
})
class AppModule {}
Run Code Online (Sandbox Code Playgroud)
现在,在解析并返回数据之前,您的路线不会被激活.
访问组件中的已解析数据
要在运行时从组件中访问已解析的数据,有两种方法.因此,根据您的需求,您可以使用以下任一方法:
route.snapshot.paramMap 返回一个字符串,或者 route.paramMap它会返回一个Observable .subscribe().例:
// the no-observable method
this.dataYouResolved= this.route.snapshot.paramMap.get('id');
// console.debug(this.licenseNumber);
// or the observable method
this.route.paramMap
.subscribe((params: ParamMap) => {
// console.log(params);
this.dataYouResolved= params.get('id');
return params.get('dataYouResolved');
// return null
});
console.debug(this.dataYouResolved);
Run Code Online (Sandbox Code Playgroud)
我希望有所帮助.
编辑:角度团队已经发布了@Resolve装饰器.它仍然需要一些澄清,如何工作,但在此之前,我将在这里采取其他人的相关答案,并提供其他来源的链接:
编辑:此答案仅适用于Angular 2 BETA.在此编辑中,未针对Angular 2 RC发布路由器.相反,当使用Angular 2 RC时,请替换为routerwith的引用router-deprecated以继续使用beta路由器.
Angular2-未来的实现方式将通过@Resolve装饰器实现.在那之前,最接近的传真是CanActivate组件装饰,每个Brandon Roberts.请参阅https://github.com/angular/angular/issues/6611
尽管beta 0不支持向Component提供已解析的值,但它是计划好的,此处还介绍了一种解决方法:在Angular2路由中使用Resolve
可在此处找到beta 1示例:http://run.plnkr.co/BAqA98lphi4rQZAd/#/resolved.它使用非常类似的解决方法,但稍微更准确地使用RouteData对象而不是RouteParams.
@CanActivate((to) => {
return new Promise((resolve) => {
to.routeData.data.user = { name: 'John' }
Run Code Online (Sandbox Code Playgroud)
另请注意,也有用于访问嵌套/父路由为例变通方法"解决"的价值观,以及和其他的功能,你期望,如果你已经使用1.x的UI的路由器.
请注意,您还需要手动注入完成此操作所需的任何服务,因为CanActivate装饰器中当前不提供Angular Injector层次结构.简单地导入一个喷油器会创建一个新的喷油器的实例,而无需访问来自供应商bootstrap(),所以你可能要存储自举喷射器的应用范围内的副本.布兰登在这个页面上的第二个Plunk链接是一个很好的起点:https://github.com/angular/angular/issues/4112