为什么在 if/else 检查来自 Europeana API 响应的 json 对象时存在不一致?

Why is there inconsistency in if/else checks of json objects from Europeana API response?

有人能解释一下为什么我对某些对象总是出错,而对其他对象却没有吗? 进行 API 调用后,响应返回一个 100 的数组。

items: Array(100)
0:
 completeness: 5
 country: ["Croatia"]
 dataProvider: ["Croatian Academy of Sciences and Arts"]
 dcLanguage: ["hr"]
 dcLanguageLangAware: {def: Array(1)}
 dcSubjectLangAware: {def: Array(2)}
 dcTitleLangAware: {def: Array(1)}
 dctermsSpatial: (2) ["http://sws.geonames.org/2950159/", "http://data.europeana.eu/place/base/2598"]

并非所有项目都具有相同的属性,但对于具有例如dcSubjectLangAware 我想遍历它们并将变体之一输出到 HTML(en、def 或 de)。如果没有 none 个,输出空字符串。

    let dcSubjectLangAware;
    if (item.dcSubjectLangAware !== undefined) {
        dcSubjectLangAware =
            item.dcSubjectLangAware.en ||
            item.dcSubjectLangAware.def[0] ||
            item.dcSubjectLangAware.hr[0] ||
            item.dcSubjectLangAware.def[1] ||
            item.dcSubjectLangAware.de[0];
    } else {
        dcSubjectLangAware = '';
    }

当某些项目具有 dcSubjectLangAware 但 none 来自语句的值但例如.it 或 .fr。它没有转到 else 并将空字符串分配给变量,而是抛出无法读取 item.dcSubjectLangAware.def[0] 的错误。当然不能,因为该项目不存在 def[0]。为什么它不循环 item.dcSubjectLangAware.def[1] || item.dcSubjectLangAware.de[0] 然后去else?它对没有任何值的项目(.en、def[0]、def[1] 或 .de[0])执行此操作,但当它偶然发现具有其他值(如 .it[0, 1,2] 或定义为 de 和 en

的多个值
de: (3) ["Deutschland", "Europe", "Travels"]
en: ["Germany"]

它抛出一个错误,而不是从 if/else 中选择一个错误。

Error TypeError: Cannot read property '0' of undefined
at europeana - working.js:73
at Array.forEach (<anonymous>)
at updateUI (europeana - working.js:47)
at europeana - working.js:36

第 73 行来自 if/elseitem.dcSubjectLangAware.def[0]。或者它停留在 item.dcSubjectLangAware.hr[0] 并抛出错误而不检查那里的 item.dcSubjectLangAware.de[0]...

总而言之,它的行为非常不一致。 这里有什么问题?支票应该有所不同吗?

不幸的是,条件 属性 运算符 ?. 在这里也无济于事。你将不得不做这样的事情

let sla=item.dcSubjectLangAware,
 dcSubjectLangAware =
  sla && (
   sla.en ||
   sla.def&&sla.def[0] ||
   sla.hr&&sla.hr[0] ||
   sla.def&&sla.def[1] ||
   sla.de&&sla.de[0] 
  ) || 'Description not available.';
    

澄清一下,Carsten 实施的更彻底的检查是必要的,即您必须检查是否有 .hr 属性,然后还有 .hr[0] 等等。

为了其他人和可读性,这里是if/else方式:

    let dcSubjectLangAware;
     if (item.dcSubjectLangAware !== undefined) {
        dcSubjectLangAware =
            (item.dcSubjectLangAware && item.dcSubjectLangAware.en) ||
            (item.dcSubjectLangAware.def && item.dcSubjectLangAware.def[0]) ||
            (item.dcSubjectLangAware.hr && item.dcSubjectLangAware.hr[0]) ||
            (item.dcSubjectLangAware.def && item.dcSubjectLangAware.def[1]) ||
            (item.dcSubjectLangAware.de && item.dcSubjectLangAware.de[0]);
    } else {
        dcSubjectLangAware = 'Description not available.';
    }

可以遍历候选语言键的数组 find 元数据 LangMap 中存在的第一个,例如item.dcSubjectLangAware,return 它的第一个值。

作为可能在其他元数据字段上重用的函数:

const localiseLangMap = (langMap, languages) => {
  let localised = '';

  if (langMap) {
    const language = languages.find(lang => langMap[lang]);
    if (language) {
      localised = langMap[language][0];
    }
  }

  return localised;
};

const languages = ['en', 'def', 'de'];
const dcSubjectLangAware = localiseLangMap(item.dcSubjectLangAware, languages);