Почему существует несогласованность в проверках if/else объектов json из ответа Europeana API?

Может ли кто-нибудь пролить свет на то, почему я продолжаю получать ошибки для одних объектов, а не для других? После вызова 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). Если их нет, вывести пустую строку.

          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, но нет значений из оператора, кроме, например, .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 - это item.dcSubjectLangAware.def [0] из if / else. Или он застревает на item.dcSubjectLangAware.hr [0] и выдает ошибку без проверки того, что там item.dcSubjectLangAware.de [0] ...

В общем, ведет себя очень непоследовательно. Что здесь не так? Должен ли чек как-то быть другим?

2 ответа

Решение

К сожалению, оператор условного свойства ?.здесь тоже не поможет. Вам нужно будет сделать что-то вроде этого

      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.';
    

Чтобы прояснить, была необходима более тщательная проверка того, что Карстен реализовал, то есть вы должны проверить, есть ли свойство .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, и вернуть его первое значение.

В качестве функции для потенциального повторного использования в других полях метаданных:

      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);
Другие вопросы по тегам