Почему существует несогласованность в проверках 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);