Использование вложенного сопоставления в подписке Observable - Angular6

Я получаю некоторые данные через вызов API (в моем файле dataservicse.ts), и получаемый мной ответ представляет собой своего рода сложную структуру JSON. Я могу получить определенную часть ответа в моем соответствующем файле компонентов следующим образом:

Вот один из ответов объекта JSON, который представляет общую структуру -

{
    "address": {
        "building": "1234",
        "coord": [0, 0],
        "street": "123 Main Street",
        "zipcode": "00000"
    },
    "address2": "Test Suite 000",
    "grades": [{
        "grade": "A",
        "score": 3
    }, {
        "grade": "B",
        "score": 4
    }, {
        "grade": "A",
        "score": 2
    }],
    "name": "John Doe",
    "_id": "1212121"
}

Теперь - моя цель - получить атрибут 'name', а также первое значение 'grade' в атрибуте grades из каждого объекта ответа - и сопоставить их в отдельные массивы, чтобы я мог отображать их в столбцах таблицы с помощью * ngFor.

Это мой код компонента

export class TestDataComponent implements OnInit {

name$: Object;
grade$: Object;

constructor(private data: DataService, private data2: DataService) { }

ngOnInit() {
   //getAPIData is returning the API response from the dataservices.ts file
   this.data.getAPIData().subscribe(
       data=>console.info(data.response.map(name=>name.name))
       ); //this works fine - I get the names in an array

     this.data2.getAPIData().subscribe(
     data2=>console.info((data2.response.map(grade=>grade.grades)).map(grades 
        => {grades.map((value, index) => value.grade})) //this returns an undefined value
  );
 }

Теперь - если я console.info((data2.response.map(grade=>grade.grades)) Я получаю массив объектов массива, таких как -

Array - [Array(3), Array(3), Array(2)]

и каждый из них состоит из атрибута 'grades' Массив объектов. (беря первый массив сверху) -

Array(3)
0:{"grade": "A","score": 3}
1:{"grade": "B", "score": 4}
2:{"grade": "A", "score": 2}

Таким образом, я дополнительно отображаю свой первоначальный ответ, чтобы получить значение «оценка». Также - мне нужен только первый класс - поэтому у меня есть простое условие, добавленное следующим образом:

console.info((data2.response.map(grade=>grade.grades))
              .map(grades 
                  => {grades.map((value, index) =>{if (index<1) value.grade})}))

Как упоминалось в комментарии - я получаю неопределенное значение.

Я понимаю, что эта проблема может быть довольно сложной, но я изо всех сил старался объяснить ее как можно яснее. Моя цель - получить первые «оценки» от каждого объекта и отобразить их в массиве - точно так же, как имена, чтобы я мог использовать его для отображения в таблице.

Я новичок в Angular6, просто перехожу с Angular 1.6, поэтому я почти уверен, что что-то напортачил.

Как лучше всего получить значения оценок в массиве с помощью вложенного сопоставления в подписке? Или есть лучший подход к тому же?

Также - для простоты игнорируйте тот факт, что присутствует первая подписка (для атрибута name) - я показал это здесь, чтобы прояснить, чего я хочу достичь.

Судя по всему, это не имеет ничего общего с Observable, вас больше беспокоит, как правильно сопоставить ваш ответ с новой структурой данных?

DavidZ 10.10.2018 18:53

Да - я не был уверен, была ли это проблема сопоставления или что-то не так с тем, как я реализую в 'subscribe' - не уверен, почему сопоставление не будет работать таким образом - я попытался разделить, сохранив каждое сопоставление в переменной и казалось, все в порядке. Но мне это нужно сразу, так как это внутри подписки. Не уверен, что это имеет смысл, при необходимости я могу предоставить более подробную информацию.

221b 10.10.2018 18:59

Вы вводите один и тот же DataService дважды? Каждый ли вызов getAPIData возвращает один и тот же объект JSON, который вы опубликовали? И почему вы пытаетесь сопоставить / уменьшить значения в подписке вместо использования конвейерной цепочки операторов?

sellmeadog 10.10.2018 19:10
Поведение ключевого слова "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
3
1 036
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы используете фигурные скобки с жирной стрелкой во второй функции карты. При использовании фигурных скобок вы должны возвращать значение с помощью ключевого слова return.

Вы имеете в виду - console.info ((data2.response.map (grade => grade.grades)). Map (gr‌ ades => {grades.map ((value, index) => {if (index <1) return value.grade})}); Это также возвращает undefined.

221b 10.10.2018 19:06

не могли бы вы добавить образец data2.response

Sachin Gupta 10.10.2018 19:13
Ответ принят как подходящий

Вот что я, считать, вы просите, поскольку вы никогда не приводили конкретного примера того, что вы пытаетесь отобразить / уменьшить. Кроме того, это ванильный JavaScript, но его можно легко перевести на RxJS.

// I am assuming that a call to `DataServce.getAPIData()` returns an array
const api_response = [{
    "address": {
        "building": "1234",
        "coord": [0, 0],
        "street": "123 Main Street",
        "zipcode": "00000"
    },
    "address2": "Test Suite 000",
    "grades": [{
        "grade": "A",
        "score": 3
    }, {
        "grade": "B",
        "score": 4
    }, {
        "grade": "A",
        "score": 2
    }],
    "name": "John Doe",
    "_id": "1212121"
}];

// Map and pluck the values you need
const result = api_response.map(v => [v.name, v.grades[0].score])

// Or as an array of objects
const obj_result = result.map(([name, score]) => ({ name, score }))

// Is this what you want?
console.info('Array', result);
console.info('Objects', obj_result);

Быстрое обновление

Спасибо, что приняли ответ. Просто хотел вкратце рассказать, как это может выглядеть при использовании RxJS. Я говорю мог бы, потому что приведенный ниже фрагмент кода не протестирован.

this.nameAndScores$ = data.getAPIData().pipe(
  map(({ response }) => response),
  map(({ name, grades }) => ( { name, score: grades[0].score } ))
)

Предполагая, что nameAndScores$ является свойством вашего экземпляра компонента, вы можете сделать *ngFor item in nameAndScores$ | async и избежать любых явных подписок в вашем коде.

Да, вы правы, он возвращает массив. Но я бы хотел получить только первый атрибут «оценка», а не «оценка». Также - можно ли это сделать в подписке без объявления константы - просто console.info сопоставленный результат?

221b 10.10.2018 19:19

Я все еще не понимаю, какую структуру данных вы хотите вернуть? Я обновил ответ, чтобы извлечь score из массива вложенных оценок. С RxJS вы выполняете ту же логику, «проталкивая» данные через серию операторов, а не «протягивая» их. const, о котором вы говорите, будет создаваться в цепочке операторов и проталкиваться через поток, а не втягиваться для обработки в subscribe.

sellmeadog 10.10.2018 19:23

Что ж, это ПОЧТИ то, что я хотел - я понимаю, что здесь делается, но проблема, которая сохраняется, заключается в том, что у меня много данных - поэтому ответ представляет собой массив объектов массива [["John Doe", 3], [" Jeff Doe ", 4], ...] - не знаю, как я могу * ngFor, чтобы в элементе <td> отображать каждое значение. Если хотите, я могу сделать скриншот того, что показывает консоль.

221b 10.10.2018 19:30

Может поможет скриншот. но даже массив [[name, score], [name, score], ...] можно легко сопоставить с [{name, score}, {name, score}, ...]. Это то, что вам нужно? Обновился снова.

sellmeadog 10.10.2018 19:37

Большое спасибо! Я полностью потерял концепцию Observable, я забыл, что могу сделать это с помощью vanilla JS - опять же, я ценю помощь!

221b 10.10.2018 19:55

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