rxjs如何在map操作中处理空值?

时间:2019-07-17 00:46:18

标签: typescript rxjs

我有一个角度服务,它从http get获取值,然后在返回时将值映射到特定对象类型的Observable。有时,属性之一的值是一个字符串,有时它是一个空值,我想将其设置为默认的空字符串。

是否有比我现有的方法更优雅的方法?

我尝试为我感兴趣的特定字段传递一个布尔值template.AreaId属性,但是我担心,随着时间的推移,更多的属性可能会出现此问题,因为创建了更多的模板对象。 / p>

getTaskFromTemplate(extraChildTask:string, hasArea: boolean) : Observable<Task>{
    if (hasArea){
      return this.templateService.getTemplateByName(extraChildTask).pipe(
        map(template => {
          return {
            WorkItemId:'',
            WorkItemType:'Task',
            Title: template.Title,
            Description: template.Description,
            AssignedTo: '',
            TeamProject: template.TeamProjectName,
            AreaPathId: template.AreaId.toString(),
            IterationPathId: '',
            Application:'',
            State:'',
            TargetDate: null,
            OriginalEstimate: 0,
            CompletedWork: 0,
            RemainingWork:0,
            BusinessPriority: '',
            CreatedBy:'',
            CreatedDate: null,
            Priority:'',
            Notes:'',
            AreaPathName:'',
            IterationPathName:'',
          }; 
        }),
        catchError((error: HttpErrorResponse) => { return throwError(error); })
      )
    }
    return this.templateService.getTemplateByName(extraChildTask).pipe(
      map(template => {
        return {
          WorkItemId:'',
          WorkItemType:'Task',
          Title: template.Title,
          Description: template.Description,
          AssignedTo: '',
          TeamProject: template.TeamProjectName,
          AreaPathId: '',
          IterationPathId: '',
          Application:'',
          State:'',
          TargetDate: null,
          OriginalEstimate: 0,
          CompletedWork: 0,
          RemainingWork:0,
          BusinessPriority: '',
          CreatedBy:'',
          CreatedDate: null,
          Priority:'',
          Notes:'',
          AreaPathName:'',
          IterationPathName:'',
        }; 
      }),
      catchError((error: HttpErrorResponse) => { return throwError(error); })
    )
  }

}

这行得通,但我希望有一种方法可以更好地处理字段为null或没有字符串值的情况。

这是我在遇到模板问题之前遇到的东西。AreaId值为null。

getTaskFromTemplate(extraChildTask:string) : Observable<Task>{
return this.templateService.getTemplateByName(extraChildTask).pipe(
    map(template => {
      return {
        WorkItemId:'',
        WorkItemType:'Task',
        Title: template.Title,
        Description: template.Description,
        AssignedTo: '',
        TeamProject: template.TeamProjectName,
        AreaPathId: template.AreaId.toString(),
        IterationPathId: '',
        Application:'',
        State:'',
        TargetDate: null,
        OriginalEstimate: 0,
        CompletedWork: 0,
        RemainingWork:0,
        BusinessPriority: '',
        CreatedBy:'',
        CreatedDate: null,
        Priority:'',
        Notes:'',
        AreaPathName:'',
        IterationPathName:'',
      }; 
    }),
    catchError((error: HttpErrorResponse) => { return throwError(error); })
  )
}

1 个答案:

答案 0 :(得分:1)

从我的评论中扩展出来,关于使用三元运算符的建议如下:

getTaskFromTemplate(extraChildTask:string) : Observable<Task>{
return this.templateService.getTemplateByName(extraChildTask).pipe(
    map(template => {
      return {
        WorkItemId:'',
        WorkItemType:'Task',
        Title: template.Title,
        Description: template.Description,
        AssignedTo: '',
        TeamProject: template.TeamProjectName,
        // Just use a ternary to prevent the `toString()` call if the property
        // does not exist on the template
        AreaPathId: template.AreaId != null ? template.AreaId.toString() : '',
        IterationPathId: '',
        Application:'',
        State:'',
        TargetDate: null,
        OriginalEstimate: 0,
        CompletedWork: 0,
        RemainingWork:0,
        BusinessPriority: '',
        CreatedBy:'',
        CreatedDate: null,
        Priority:'',
        Notes:'',
        AreaPathName:'',
        IterationPathName:'',
      }; 
    }),
    catchError((error: HttpErrorResponse) => { return throwError(error); })
  )
}

还扩展了我所说的动态映射属性的潜力(即避免明确指定所涉及的每个属性的映射),一种可能的解决方案的示例可能如下所示:

const { of } = rxjs;
const { map } = rxjs.operators;

const baseTask = {
    Title: '',
    Description: '',
    TeamProjectName: '',
    AreaPathId: '',
    WorkItemId: '',
    WorkItemType: 'Task',
    // ...
};

function getTaskFromTemplate(extraChildTask, hasArea) {
  return getTemplateByName(extraChildTask).pipe(
    map(template => {
      // Merges properties the acquired template with those in the base task
      // with the properties in the template taking precedence
      return Object.assign({}, baseTask, template);
    }),
  );
}

// Stub implementation that just returns a fixed template
function getTemplateByName(extraChildTask) {
  return of({
    Title: 'Title',
    Description: 'Description',
    TeamProjectName: 'Team Project Name',
    AreaPathId: 'Area Path ID',
    // ...
  });
}

// Example usage in action
getTaskFromTemplate('something').subscribe(task => {
  console.log(task);
});
<script src="https://unpkg.com/rxjs@6.5.2/bundles/rxjs.umd.min.js"></script>

正如我指出的,如果某些任务属性名称与您需要映射的模板名称不匹配,则可以通过设置一些其他映射步骤来解决。