Javascript обрабатывает различные ответы на запрос ajax, а response.length = undefined

У меня есть запрос ajax, который возвращает json. Если есть одна запись, она возвращает это:

{"key":"My Value 1"}

Если возвращается более одной записи, это массив объектов:

[{"key":"My Value 1"},{"key":"My Value 2"}]

Я хотел бы просто иметь цикл, который обрабатывал бы 1 или несколько возвращаемых объектов, но когда я возвращаю только один объект, response.length не определено:

      console.info(typeof response); //Object
      console.info(response.length); //undefined

      row = '';
      Object.values(response).forEach(function(val) {
        row += '<tr><td>' + val + '</td></tr>';
      });

Проблема в том, что значение response.length не определено, но есть одна возвращенная запись. Я думаю, если бы был возвращен один объект, длина была бы 1? Как проверить один объект, а также обработать несколько? Я думаю, должен быть простой/гибкий способ сделать это?

Либо измените код на сервере, чтобы он всегда возвращал массив элементов, либо просто оберните ответ в массив на клиенте, если это объект.

Andreas 24.02.2019 17:13

держите ответ последовательным

Hafeez Hamza 24.02.2019 17:15
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
49
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Попробуйте использовать Object.keys(response).length вместо длины.

Ответ принят как подходящий

Лучше исправить на сервере. Если нет возможности сделать

response = response.length?response:[response];

Например

let response = {"key":"My Value 1"}
response = response.length?response:[response]; // force array if no length
tb.innerHTML = response.map((obj) => '<tr><td>' + obj["key"] + '</td></tr>')
  .join("")


response = [
  {"key":"My Value 2"},
  {"key":"My Value 3"}
];
response = response.length?response:[response]; // force array if no length
//console.info(response)
tb.innerHTML += response.map((obj) => '<tr><td>' + obj["key"] + '</td></tr>')
  .join("");
<table>
<tbody id = "tb"></tbody>
</table>

Думаю исправлю на сервере. У меня он динамически возвращал строку или объект, используя активную запись, но я понимаю, что это усложняет ситуацию, и я всегда должен возвращать одно и то же... спасибо!

hyphen 24.02.2019 17:18

Вы можете проверить, является ли ответ массивом, используя Array.isArray(response), Если это не массив, создайте массив, используя ответ, и после этого повторите его.

const responseArray = Array.isArray(response) ? response : [response];
responseArray.forEach(element => { // do your thing })

Вы можете проверить тип ответа, если это массив, Array#isArray будет истинным, а с помощью Array#reduce мы можем сократить строку путем конкатенации.

В противном случае, если это один объект, мы можем просто извлечь ключ и сформировать строку.

Но лучше исправить backend API каждый раз возвращать массив. Если это не вариант, используйте решение ниже.

function generateTableRow(response){
  let row = '';
  if (Array.isArray(response)){
   row = response.reduce((acc, {key}) =>{ //using destructuring to get the 'key'
       return acc + `<tr><td>${key}</td></tr>`;
    }, '');
  }else{
   row = `<tr><td>${response.key}</td></tr>`;
  }
  return row;
}
let response = [{"key":"My Value 1"},{"key":"My Value 2"}];
console.info("If array sent");
console.info(generateTableRow(response));
response = {"key":"My Value 1"};
console.info("If object sent");
console.info(generateTableRow(response));

Зачем уменьшать? Почему не карту? Я считаю использование сокращения, когда у вас есть результат один к одному, неправильное использование

mplungjan 24.02.2019 17:30

@mplungjan на самом деле я пытался собрать значения объекта в одну строку, поэтому я подумал об использовании сокращения. Пожалуйста, поправьте меня, если я ошибаюсь, но использование карты приведет к массиву, для которого мне снова нужно использовать соединение (""), чтобы получить результат. Поскольку OP хочет, чтобы конечным результатом была строка :)

Fullstack Guy 24.02.2019 17:38

Да вы правы. У меня нет проблем с присоединением, как показано в моем обновленном ответе.

mplungjan 24.02.2019 17:44

Другие вопросы по теме