简体   繁体   English

在Angular App中对网络请求之前的空对象使用条件检查

[英]Using Conditional Check on Empty Object Before Network Request in Angular App

I have a function that takes in filter values and the passes a network request in my Angular app. 我有一个函数,它接受过滤器值并在Angular应用程序中传递网络请求。 Because I'm running into issues where the network request is made before the filters arrive, I've tried setting up some conditional checks to not make the network request until the filter values are available. 因为我遇到了在过滤器到达之前发出网络请求的问题,所以我尝试设置一些条件检查以在过滤器值可用之前才发出网络请求。 It's not the ideal solution, but I'm trying to get something working (for now) on short notice. 这不是理想的解决方案,但我正在努力(暂时)在短时间内使某些工作正常。

This is my code. 这是我的代码。 First, I set up a function to check if an object is empty or not. 首先,我设置了一个函数来检查对象是否为空。 I do this because I want to only fire my network request once I have a non-empty object. 之所以这样做,是因为我只想在拥有非空对象后才触发网络请求。 And the object will be non-empty once the filter values have been applied. 一旦应用了过滤器值,该对象将为非空。 Here's the code: 这是代码:

isEmptyObj(obj) {
    return Object.keys(obj).length === 0;
}

public async onFilterReceived(values) {
    let filters = {};

    if (!values) return;

    if (values) {
        filters = values;
    }

    this.route.params.subscribe(
        (params: any) => {
            this.page = params['page'];
        }
    );

    let fn = resRecordsData => {
        this.records = resRecordsData;
    };

    // Make request IF filters is NOT empty object (i.e. it has values)
    if (!this.isEmptyObj(filters)) {
        console.log('filter values within cond call: ', filters); // should not be empty
        console.log('firstName within cond call: ', filters['firstName']); // should not be empty in this case as I selected a firstName value
        console.log('should be false: ', this.isEmptyObj(filters)); // should be false
        this.streamFiltersService.getByFilters(
            this.page - 1, this.pagesize, this.currentStage, this.language = filters['language'], this.location = filters['location'],
            this.zipcode = filters['zip'], this.firstName = filters['firstName'], this.lastName = filters['lastName'],
            this.branch = filters['branch'], fn);
    }
}

Clearly this is not working as intended. 显然,这没有按预期进行。 When I look at what logs to the console from WITHIN the conditional section, I see 'filters' and 'firstName' as empty values. 当我在条件部分中查看从控制台记录到控制台的内容时,我看到“过滤器”和“名字”为空值。 In other words, my conditional check is not working as I intended it to. 换句话说,我的条件检查无法按预期工作。 What am I missing here? 我在这里想念什么? How could I approach this differently so that the network request is only made once I have the values? 如何处理不同的问题,以便仅在拥有值后才发出网络请求?

By the way, when I console.log values , this is what I get: 顺便说一句,当我console.log values ,这就是我得到的:

{zip: Array(0), firstName: Array(0), lastName: Array(0), language: Array(0), location: Array(0), …}

By the way, earlier console logs I used demonstrate that initially filters is an empty object. 顺便说一下,我以前使用的控制台日志演示了最初的filters是一个空对象。 It's only I assign values to filters that it is no longer an empty object. 只是我为filters分配了values ,它不再是一个空对象。

So, why then is my conditional check before the network request working as intended? 那么,为什么在网络请求按预期方式工作之前我的条件检查呢?

Within the if conditional I see this console.log: 在if条件中,我看到以下console.log:

filter values within cond call:  {zip: Array(0), firstName: Array(0), lastName: Array(0), language: Array(0), location: Array(0), …}

Help me understand how this is happening based on my above code. 根据我上面的代码,帮助我了解情况如何。

The first issue is that the method isEmptyObj(obj) to check for keys isn't working as you are expecting. 第一个问题是,用于检查密钥的isEmptyObj(obj)方法无法正常工作。 This is because the sample values you provided: 这是因为您提供的样本values

{zip: Array(0), firstName: Array(0), lastName: Array(0), language: Array(0), location: Array(0), …}

Even though it is only empty arrays, that still has keys, so that method isEmptyObj will return false for that sample value. 即使只是空数组,它仍然具有键,因此isEmptyObj方法将对该样本值返回false The only time it would return false would be for a plain empty object {} . 它唯一返回false的时间是针对普通的空对象{}

 function isEmptyObj(obj) { return Object.keys(obj).length === 0; } console.log(isEmptyObj({})); console.log(isEmptyObj({ zips: [] })); 

So change that to something like where you filter "falsy" values based on length : 因此,将其更改为类似于您根据length过滤“虚假”值的地方:

 function isEmptyObj(obj) { return Object.keys(obj).map(key => obj[key]).filter(v => v.length > 0).length === 0; } console.log(isEmptyObj({ })); console.log(isEmptyObj({ zip: [] })); 

The next issue is the flow of onFilterReceived . 下一个问题是onFilterReceived的流程。 It does not need to be an async , method, also this.route.params.subscribe() will effectively always execute after the rest of the code in the method. 它不必是async方法,而且this.route.params.subscribe()将始终在该方法中的其余代码之后有效地执行。 Try the following by moving everything into subscribe() at the very minimum. 通过将所有内容移到最起步来尝试以下操作。 Keep in mind you need to subscribe() to an HTTP calls to actually get them to execute: 请记住,您需要subscribe()进行HTTP调用才能实际执行它们:

public onFilterReceived(values) {
    let filters = {};

    if (!values) return;

    if (values) {
        filters = values;
    }

    this.route.params.subscribe((params: any) => {
        this.page = params['page'];

        let fn = resRecordsData => (this.records = resRecordsData);

        // Make request IF filters is NOT empty (i.e. it has values)
        if (!this.isEmptyObj(filters)) {
          this.streamFiltersService.getByFilters(
            this.page - 1, this.pagesize, this.currentStage, this.language = filters['language'],
            this.location = filters['location'],
            this.zipcode = filters['zip'], this.firstName = filters['firstName'], this.lastName = filters['lastName'],
            this.branch = filters['branch'],
            fn
          )
          .subscribe(results => console.log(results));
        }
      });
   );
}

You can use operators such as switchMap , takeWhile , and tap to streamline the Observable portion: 您可以使用switchMaptakeWhile之类的运算符,然后点击来简化Observable部分:

import { switchMap, takeWhile, tap } from 'rxjs/operators';

// ..

public onFilterReceived(values) {
    let filters = {};

    if (!values) return;

    if (values) {
        filters = values;
    }

    this.route.params.pipe(
        tap((params: any) => this.page = params['page']),
        takeWhile(_ => !this.isEmptyObj(filters)),
        switchMap((params: any) => {
            let fn = resRecordsData => (this.records = resRecordsData);

            return this.streamFiltersService.getByFilters(
                this.page - 1, this.pagesize, this.currentStage, this.language = filters['language'],
                this.location = filters['location'],
                this.zipcode = filters['zip'], this.firstName = filters['firstName'], this.lastName = filters['lastName'],
                this.branch = filters['branch'],
                fn
            );
        });
    ).subscribe(results => console.log(results));
}

Hopefully that helps! 希望有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM