我试图了解为什么我的Angular应用程序中的某些逻辑导致对API的无限调用。清楚的是,我想确定一种更好的方法。
首先,在我看来,我对一个看起来像这样的按钮进行了验证:
<button md-button (click)="completeCategory()"
[disabled]="!canComplete()"
[class.button-disabled]="!canComplete()">Complete
</button>
现在,作为我组件中验证的一部分,我调用了API来检查一些数据:
public async isDocSigned() {
const customerId = this.customer._id;
const type = 'catOrig';
const response: any = await this.stageService.checkSignedDoc(customerId, type);
// Look for errors
if (!response || response.ok !== true)
{
let message = 'Failed to obtain signature data';
console.error(message, response);
return;
}
if (response && response.count > 0) {
return true;
} else if (response && response.count < 1) {
return false;
}
}
顺便说一句,上面调用的服务函数如下:
public async checkCustomerSigned(customerId, type) {
return await API.service.send({
reqType: 'get',
req: `customers/validation/ptlDocument`,
reqArgs: { customer: customerId, type: type }
});
}
然后,我将返回的API响应用作条件逻辑的一部分,以查看是否应启用带有canComplete()
按钮的按钮。
要考虑两个条件因素。 1.)文档是否处于正确的阶段; 2。)如果是,则说明文档已签名:
public async canComplete() {
if (this.selectedService.category['stage'] === 'awaiting signature from customer') {
const docSigned = await this.isDocSigned();
if (docSigned) return true;
if (!docSigned) return false;
}
}
因此,通过测试此代码,可以清楚地发现isDocSigned()
函数会反复调用API。
我认为这是因为Angular在视图中看到带有canComplete()
函数的按钮,然后不断对其进行评估吗?
当文档处于此阶段时,我最终看到的是这个console.log行一次又一次地打印到屏幕上:
`console.error(message, response);`
那么解决这个问题的更好方法是什么?我应该将isDocSigned()
放在构造函数中,还是放在生命周期挂钩之类的ngOninit()
中?我如何在这里解决无限通话?理想情况下,我只想进行一次此API调用。我真的很欣赏如何执行此操作的示例。一个简单的stackBlitz示例将非常有帮助。
答案 0 :(得分:1)
首先是由于Angular Change Detection导致调用API的原因。在HTML文件中,您正在调用一个函数,而Angular不知道该函数的返回类型是否已更改。因此,它将继续执行导致无限API调用的函数。下面是错误的代码:
[class.button-disabled]="!canComplete()"
强烈建议不要在模板中使用函数。可以更改为使用以下内容:
[class.button-disabled]="!docSigned"
并将canComplete()方法移动到ngOnInint。请注意,这将仅在页面加载时限制对API的调用。
答案 1 :(得分:-1)
public async canComplete() {
if (this.selectedService.category['stage'] === 'awaiting signature from customer') {
if(this._docSigned !== undefined) {
return this._docSigned;
}
return this._docSigned = await this.isDocSigned();
}
}