Я получаю некоторые данные через вызов 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) - я показал это здесь, чтобы прояснить, чего я хочу достичь.
Да - я не был уверен, была ли это проблема сопоставления или что-то не так с тем, как я реализую в 'subscribe' - не уверен, почему сопоставление не будет работать таким образом - я попытался разделить, сохранив каждое сопоставление в переменной и казалось, все в порядке. Но мне это нужно сразу, так как это внутри подписки. Не уверен, что это имеет смысл, при необходимости я могу предоставить более подробную информацию.
Вы вводите один и тот же DataService дважды? Каждый ли вызов getAPIData возвращает один и тот же объект JSON, который вы опубликовали? И почему вы пытаетесь сопоставить / уменьшить значения в подписке вместо использования конвейерной цепочки операторов?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы используете фигурные скобки с жирной стрелкой во второй функции карты. При использовании фигурных скобок вы должны возвращать значение с помощью ключевого слова return.
Вы имеете в виду - console.info ((data2.response.map (grade => grade.grades)). Map (gr ades => {grades.map ((value, index) => {if (index <1) return value.grade})}); Это также возвращает undefined.
не могли бы вы добавить образец data2.response
Вот что я, считать, вы просите, поскольку вы никогда не приводили конкретного примера того, что вы пытаетесь отобразить / уменьшить. Кроме того, это ванильный 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 сопоставленный результат?
Я все еще не понимаю, какую структуру данных вы хотите вернуть? Я обновил ответ, чтобы извлечь score из массива вложенных оценок. С RxJS вы выполняете ту же логику, «проталкивая» данные через серию операторов, а не «протягивая» их. const, о котором вы говорите, будет создаваться в цепочке операторов и проталкиваться через поток, а не втягиваться для обработки в subscribe.
Что ж, это ПОЧТИ то, что я хотел - я понимаю, что здесь делается, но проблема, которая сохраняется, заключается в том, что у меня много данных - поэтому ответ представляет собой массив объектов массива [["John Doe", 3], [" Jeff Doe ", 4], ...] - не знаю, как я могу * ngFor, чтобы в элементе <td> отображать каждое значение. Если хотите, я могу сделать скриншот того, что показывает консоль.
Может поможет скриншот. но даже массив [[name, score], [name, score], ...] можно легко сопоставить с [{name, score}, {name, score}, ...]. Это то, что вам нужно? Обновился снова.
Большое спасибо! Я полностью потерял концепцию Observable, я забыл, что могу сделать это с помощью vanilla JS - опять же, я ценю помощь!
Судя по всему, это не имеет ничего общего с Observable, вас больше беспокоит, как правильно сопоставить ваш ответ с новой структурой данных?