检查 Store 在调用 NgRx Angular API 之前

4
我正在创建一个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个回答

5

做出一些约定:

  1. state.Companies = null是当尚未向服务器发送请求时的初始状态
  2. state.Companies = []是在第一个请求已被发送但服务器没有返回公司时的状态
  3. 使用createSelector根据所需的标准过滤公司
  4. 在你的effect中使用withLatestFrom,这将使你能够检查存储状态

现在,反过来思考逻辑:

  1. 查找公司时,首先触发一个操作,该操作将触发effects
  2. 在该效果中,检查state.Companies是否为null
  3. 如果它是null,则触发api请求
  4. 如果不是null,则触发一个操作,该操作将触发用于过滤的选择器
  5. 如果即使state.Companies不是null也无法找到数据,则意味着您需要刷新Companies集合或该值不存在于服务器上

实际上我正在使用ngrx entity。所以我认为默认情况下它不允许有空实体。那么使用额外的标志来检查值是否存在于存储中呢? - Shahrukh Shahid
是的,那也可以。再次,给予该标志(心理)意义,以便区分实体未在存储中找到和实体根本不存在于服务器上的情况。 - dee zg

3
创建另一个名为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);
                }
              });
            }
          });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接