在Angular App条件逻辑中防止对API的无限调用

时间:2018-12-19 13:32:41

标签: angular

我试图了解为什么我的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示例将非常有帮助。

2 个答案:

答案 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();
  }
}