You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AngularJS中判断API返回变量是否存在的问题排查

解决AngularJS+HAML中判断media.metadata.date_time_original存在性避免报错的问题

我在使用AngularJS、CoffeeScript和HAML进行前端开发时,遇到了一个问题:从API获取包含图片属性的JSON元数据对象后,需要判断media.metadata.date_time_original属性是否存在来决定是否显示,但控制台一直抛出TypeError: Cannot read property 'date_time_original' of null的错误。下面是我的现有代码、报错信息,以及对应的解决办法:

现有CoffeeScript数据获取代码

getImages = -> 
  listImage = [] 
  for sheet in $scope.report.report_sheets() 
    for composed in sheet.report_fragments() 
      for fragment in composed.report_fragments() 
        if fragment.fragment_type is 'images' 
          for media in fragment.media() 
            if media.metadata.date_time_original 
              media.metadata.date_time_original = moment.utc(media.metadata.date_time_original).local().format('DD-MMM-YYYY h:mm A') 
              listImage.push media 
  listImage 

现有HAML视图代码

.directive-report-images{ ng_show: 'conditionIsChecked && fragment._parentConditionChecked' }
  .row
    .col-md-4
      .title
        %h5.black {{ fragment.title }}
    .col-md-8
      %report_fragment_visibility
  .row{ ng_if: 'fragment.media().length <= 2' }
    .col-md-6.thumbnail{ ng_repeat: "img in fragment.media() | notArchived | orderBy:'order'" }
      %img.pointer{ ng_src: "{{ img.contentUrl() }}", ng_click:'openCarouselModal(img)' }
      %p {{ img.comment }}
      .photo-date{ng_if: "img.metadata.date_time_original" }
        %p {{ img.metadata.date_time_original}}
  .row{ ng_if: 'fragment.media().length > 2' }
    .col-md-12
      .row
        .col-md-4.thumbnail{ ng_repeat: "img in fragment.media() | notArchived | orderBy:'order'" }
          %img.pointer{ ng_src: "{{ img.contentUrl() }}", ng_click:'openCarouselModal(img)' }
          %p {{ img.comment }}
          %p.photo-date {{ img.metadata.date_time_original }}

当前控制台报错

TypeError: Cannot read property 'date_time_original' of null


问题根源

报错的核心原因是:部分media对象的metadata属性为null,当代码直接访问null.date_time_original时,就会触发类型错误。我们需要在数据预处理阶段和视图渲染阶段都添加防御性检查,双管齐下解决问题。

解决方案

1. 在CoffeeScript中提前处理metadata为null的情况

修改数据获取的循环逻辑,先确保media.metadata不是null/undefined,再去判断date_time_original是否存在:

getImages = -> 
  listImage = [] 
  for sheet in $scope.report.report_sheets() 
    for composed in sheet.report_fragments() 
      for fragment in composed.report_fragments() 
        if fragment.fragment_type is 'images' 
          for media in fragment.media() 
            # 用CoffeeScript安全导航符先校验metadata存在,再判断日期属性
            if media.metadata?.date_time_original 
              media.metadata.date_time_original = moment.utc(media.metadata.date_time_original).local().format('DD-MMM-YYYY h:mm A') 
              listImage.push media 
            # 额外优化:给null的metadata赋值空对象,避免后续视图访问报错
            else if not media.metadata
              media.metadata = {}
  listImage 

这里的?.是CoffeeScript的安全导航操作符,会自动判断media.metadata是否存在,不存在则直接返回undefined,不会触发报错。同时给null的metadata赋值空对象,后续视图访问属性时就不会因为null抛出异常。

2. 在HAML视图中添加多层存在性判断

即使后台处理了数据,视图层也要做兜底校验,避免API返回异常数据的情况:

修改HAML中两处日期相关的代码:

# 针对图片数量<=2的场景,修改ng-if判断条件
.photo-date{ng_if: "img.metadata && img.metadata.date_time_original" }
  %p {{ img.metadata.date_time_original}}

# 针对图片数量>2的场景,添加判断后再渲染日期
%p.photo-date{ ng_if: "img.metadata && img.metadata.date_time_original" } {{ img.metadata.date_time_original }}

这里的img.metadata && img.metadata.date_time_original会先判断img.metadata是否有效(不是null/undefined),再判断date_time_original是否有值,只有两者都满足时才会渲染日期元素。

效果验证

经过以上修改后:

  • 当media.metadata为null时,代码不会尝试访问它的属性,彻底避免报错
  • 只有当date_time_original存在且有效时,才会在视图中显示日期
  • 完全实现了“存在则显示,不存在则不显示”的预期逻辑

内容的提问来源于stack exchange,提问作者user9569059

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:39:47