在API调用NgRx Angular之前检查Store

时间:2018-08-17 12:57:30

标签: javascript angular typescript rxjs ngrx

我正在创建NgRx应用程序,但由于它是我的第一个使用NgRx的应用程序,因此对其实现感到非常困惑。 我有一家状态为“公司” 的商店。我要搜索公司,如果找到就返回。 如果找不到所需的公司,则应调用API并同样获取结果,但是该过程是循环的,并且运行时间无限长。

这是我的代码:

    this.companySearchCtrl.valueChanges
      .pipe(
        debounceTime(300),
        distinctUntilChanged()
      )
      .subscribe(val => {
        if (val !== ' ' || val !== '') {
          this.store.select(getCompanys).subscribe(data => {
            console.log(data);
//filter companies on the basis of search text
            const filteredData = data.filter(x =>
              x['name']
                .toLowerCase()
                .startsWith(this.companySearchCtrl.value.toLowerCase())
            );
            console.log(filteredData);
            if (filteredData.length === 0) { //if data is not found in store
              console.log('got a call');
              this.store.dispatch(
                new CompanyActions.find({
                  where: { name: { regexp: `${val}/i` } } // call to API to search with regExp
                })
              );
            } else {
// if required data found in store
              console.log('got no call');
              this.filteredCompanies$ = of(filteredData);
            }
          });
        }
      });

如果在存储中找到数据,则此过程运行良好。如果在商店中找不到数据,或者我没有从API调用中得到任何结果,它将无限期运行。 我该如何纠正?

2 个答案:

答案 0 :(得分:3)

制定一些约定:

  1. state.Companies = null是初始状态,如果尚未发送对服务器的请求
  2. state.Companies = []处于发送第一个请求后的状态,但服务器未返回任何公司
  3. 使用createSelector根据您需要的条件过滤您的公司
  4. 在效果中使用withLatestFrom,这将使您能够检查效果中的存储状态

现在,将逻辑反过来:

  1. 寻找公司时,请先触发会触发效果的动作
  2. 为此,请检查state.Companies是否为null
  3. 如果其null>消防API请求
  4. 如果其不为null>,则触发将触发选择器进行过滤的操作
  5. 如果即使没有state.Companies都没有找到数据,则意味着您需要刷新null集合,或者服务器上的值不存在

答案 1 :(得分:2)

创建另一个名为dataNotFound的动作。如果找到数据,则将其状态isFound设置为true,如果找不到数据,则将其状态isFound设置为false,并始终在发送带有正则表达式的调用之前,先检查isFound是否找到了数据是否在之前的通话中。如果找不到数据,请不要再发送呼叫。

我已经对您的代码进行了一些更改以进行管理。您只需要立即创建一个动作dataNotFound

     this.companySearchCtrl.valueChanges
          .pipe(
            debounceTime(300),
            distinctUntilChanged()
          )
          .subscribe(val => {
            if (val !== ' ' || val !== '') {
              this.store.select(getCompanys).subscribe(data => {
                console.log(data);
    //filter companies on the basis of search text
                const filteredData = data.filter(x =>
                  x['name']
                    .toLowerCase()
                    .startsWith(this.companySearchCtrl.value.toLowerCase())
                );
                console.log(filteredData);
                if (filteredData.length === 0) { //if data is not found in store
                  console.log('got a call');
                  this.store.select(isDataFound).subscribe(isFound => {
                      if(isFound) {
                          this.store.dispatch(
                          new CompanyActions.find({
                       where: { name: { regexp: `${val}/i` } } // call to API to 
                                                                search with regExp
                    })
                  );
                      } else {
                          this.store.dispatch(new CompanyActions.dataNotFound({isFound: false}));
                      } 
                  });

                } else {
    // if required data found in store
                  console.log('got no call');
                  this.store.dispatch(new CompanyActions.dataNotFound({isFound: true}));  
                  this.filteredCompanies$ = of(filteredData);
                }
              });
            }
          });