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

时间:2018-09-27 20:06:35

标签: javascript angular typescript

我有一个函数,该函数接受过滤器值并在Angular应用中传递网络请求。因为我遇到了在过滤器到达之前发出网络请求的问题,所以我尝试设置一些条件检查以在过滤器值可用之前才发出网络请求。这不是理想的解决方案,但我正在努力(暂时)在短时间内使某些工作正常。

这是我的代码。首先,我设置了一个函数来检查对象是否为空。之所以这样做,是因为我只想在拥有非空对象后才触发网络请求。一旦应用了过滤器值,该对象将为非空。这是代码:

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);
    }
}

很显然,这无法正常工作。当我在条件部分中查看从控制台记录到控制台的内容时,我看到“过滤器”和“名字”为空值。换句话说,我的条件检查无法按预期工作。我在这里想念什么?我该如何以不同的方式处理,以便仅在拥有值后才发出网络请求?

顺便说一句,当我console.log values时,这就是我得到的:

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

顺便说一下,我以前使用的控制台日志演示了最初的filters是一个空对象。只是我将values分配给filters不再是空对象。

那么,为什么在网络请求按预期工作之前我的条件检查呢?

如果有条件,我会看到此console.log:

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

根据我上面的代码,帮助我了解情况如何。

1 个答案:

答案 0 :(得分:1)

第一个问题是,用于检查密钥的方法isEmptyObj(obj)并没有按您期望的那样工作。这是因为您提供了示例values

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

即使只是空数组,它仍然具有键,因此方法isEmptyObj将为该样本值返回false。唯一会返回false的时间是针对普通的空对象{}

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

console.log(isEmptyObj({}));
console.log(isEmptyObj({ zips: [] }));

因此将其更改为类似根据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: [] }));

下一个问题是onFilterReceived的流程。它不必是async方法,this.route.params.subscribe()也将始终在该方法中的其余代码之后有效地执行。通过将所有内容移到最起步来尝试以下操作。请记住,您需要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));
        }
      });
   );
}

您可以使用switchMaptakeWhiletap之类的运算符来简化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));
}

希望有帮助!