首页 > 解决方案 > 防止在 Angular 应用条件逻辑中无限调用 API

问题描述

我试图了解为什么我的 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.) 如果是 s,文档是否已签名:

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 示例将非常有帮助。

标签: angular

解决方案


首先是由于 Angular Change Detection 而调用 API 的原因。在您的 HTML 文件中,您正在调用一个函数,而 Angular 不知道该函数的返回类型是否已更改。因此,它会继续执行导致无限 API 调用的函数。下面是错误代码:

[class.button-disabled]="!canComplete()"

强烈建议不要在模板中使用函数。这可以更改为使用以下内容:

[class.button-disabled]="!docSigned"

并将 canComplete() 方法移动到 ngOnInint。请注意,这将限制对 API 的调用仅在页面加载时。


推荐阅读