我注意到使用Angular 2的组件有一种奇怪的行为。 一旦我的组件更改作为我的提供者包含的模型,我的视图需要几秒钟才能更新。即使来自API的数据是单个数据。
例如:
我有一个名为UserModel的模型作为我的提供者 在我的组件内部,我从API获取数据,然后更新此模型,这也在我的视图中。 从服务器获得响应后,更新我的视图仍然需要几秒钟,有时它不会更新,只需在我点击同一页面上的任何文本控制器后,我的视图会在任何文本获得焦点后更新。 / p>
有没有人见过这个?我能做错什么?
卡组件
public createCard(model:CardModel):Promise<any>{
var context = this;
return new Promise((resolve, reject) => {
this.stripe.createToken(model)
.then(function(token){
model.token = token;
context.saveCard("./card", model, true)
.then(data => resolve(data))
.catch(error => reject(error));
})
.catch(error => reject(error));
});
条纹服务
public createToken(model:CardModel):Promise<any>{
//I get callback and convert return it as promise
return new Promise((resolve, reject) => {
//this function is the one from stripe.js, it is not promise
this.stripe.card.createToken(model, function(status, response){
if(status == 200){
resolve(response.id);
}else{
reject(response.error.message);
}
});
});
}
如果您注意到函数createToken返回为回调,因为它是一个Strip.js函数,然后我将其转换为Promise以将其返回到createCard。但是一旦完成所有功能,我的区域就不会改变。如果我删除this.stripe.card.createToken并使用超时返回一个简单的resolve(),它可以正常工作。所以我认为问题是什么时候有异步函数在Promise中返回回调。但我不知道如何处理它。
答案 0 :(得分:0)
似乎您使用的是与Angular 2不兼容的第三方库。我遇到了与StripeJS相同的问题。这个问题与Angular的Zone.js和生命周期有关 - 它与Angular 1中糟糕的摘要周期问题非常相似.Angular在这里有关于解决方案的详细文档:https://angular.io/api/core/ChangeDetectorRef#example-live-demo
为了解决这个问题,您必须实现自己的生命周期循环并将第三方库添加到更改检测中。 我对StripeJS的实现(还记得使用clearInterval销毁setInterval:
import {
Component,
Input,
Output,
EventEmitter,
AfterContentInit,
ChangeDetectorRef,
ChangeDetectionStrategy,
ViewContainerRef,
OnDestroy
} from '@angular/core';
@Component({
selector: 'v-payment-form', // <payment-form></payment-form>
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './payment-form.component.html'
})
export class PaymentFormComponent implements AfterContentInit, OnDestroy {
checker: any;
constructor(private changeDetectorRef: ChangeDetectorRef) {
this.checker = setInterval(() => {
// the following is required, otherwise the view will not be updated
this.changeDetectorRef.markForCheck();
}, 75);
}
addPaymentMethod() {
Stripe.card.createToken(cardDetails)
this.changeDetectorRef.detectChanges()
}
ngAfterContentInit() {
// ..load stripe js here - I use scriptjs
}
ngOnDestroy(): void {
clearInterval(this.checker)
}
}