Angular - как получить результат объекта JSON?

Я пытаюсь использовать новый публичный API V2 CoinMarketCap, но у меня возникают некоторые трудности с этим.

JSON:

https://api.coinmarketcap.com/v2/ticker/?limit=10

моя модель монеты:

export class Coins {
    id: string;
    name: string;
    symbol: string;
    rank: number;
    price_usd: number;
    price_btc: number;
    _24h_volume_usd: number;
    market_cap_usd: number;
    available_supply: number;
    total_supply: number;
    percent_change_1h: number;
    percent_change_24h: number;
    percent_change_7d: number;
    last_updated: number;
}

моя служба:

urlBase = 'https://api.coinmarketcap.com/v2/ticker/?limit=10';
getCoins() {
   return Observable
   .timer(0, 5000)
   .flatMap(() =>  this.http.get(this.urlBase))
   .pipe(
      map(res => res), 
      catchError(this.handleError)
    )
}

мой компонент:

coins: Coins[];
getCoins() {
  this.coinsService.getCoins().subscribe(
    data => {
      this.coins = data;
    });
}

мой HTML:

<div class = "card card-inverse" *ngFor = "let coin of coins">

выход:

ERROR Error: Cannot find a differ supporting object '[object Object]' of type 
'object'. NgFor only supports binding to Iterables such as Arrays.

любое предложение?

Спасибо

Не могли бы вы показать определение для Coin, пожалуйста

Jamie Rees 15.06.2018 09:16

Попробуйте использовать * ngFor = «пускать монету в монеты».

Carnaru Valentin 15.06.2018 09:23

Может ли это помочь? stackoverflow.com/questions/39761673/…

mtefi 15.06.2018 09:26
Поведение ключевого слова "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
4
9 136
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

Попробуйте код ниже в вашем файле mycomponent.

getCoins() {
this.coinsService.getCoins().subscribe(
    data => {
        let coins = [];
        for (let key in data) {
            coins.push(data['key']);
        }
      this.coins = coins;
    });
}
Ответ принят как подходящий

Из данных api, которые вы показываете, я вижу, что вы назначаете this.coins объекту, а не массиву. Вы должны сначала преобразовать его в массив, а затем назначить его this.coins.

getCoins() {
  this.coinsService.getCoins().subscribe(
    data => {
      this.coins = [];
      for(let key in data){
          this.coins.push(data[key]);
       }
    });
}

Или вы также можете сделать этот способ для преобразования объекта в массив.

getCoins() {
      this.coinsService.getCoins().subscribe(
        data => {
          this.coins = [];
          Object.keys(data).map((key)=>{ this.coins.push(data[key]) });
        });
}

В вашем служебном файле

getCoins() {
    return this.http.get(this.urlBase).pipe(map(res => res = res.json()['data']))
}

Рабочий ДЕМО

Привет, Амит, спасибо за ответ. В обоих случаях у меня есть вывод: ERROR TypeError: Невозможно прочитать свойство push of undefined.

Marcio 15.06.2018 09:43

Во время декларации инициализируйте свои монеты как coins : Coins[] = [];.

Amit Chigadani 15.06.2018 09:45

@Michael Если вы не инициализируете массив coins с пустым массивом [], вам придется использовать временный массив, а затем назначить его. Лучше всего, если вы инициализируете внутри самой функции, если не во время объявления.

Amit Chigadani 15.06.2018 09:53

хорошо, у меня нет ошибки, но на экране ничего не отображается. Как это должно быть в html?

Marcio 15.06.2018 09:54

Измените свой служебный файл соответствующим образом, и я добавил демонстрацию для вашей справки.

Amit Chigadani 15.06.2018 10:21

Да, у меня работает !! Вместо res = res.json () только res = res

Marcio 15.06.2018 12:00

this.coins = data.json() или вы можете использовать наблюдаемый.
в html <div class = "card card-inverse" *ngFor = "let coin of coins | async">
в компоненте

coins: Observable<Coin[]>;

getCoins() { this.coins = this.coinsService.getCoins(); }

в сервисе:

getCoins(): Observable<any> {
  const api = 'https://api.coinmarketcap.com/v2/ticker/?limit=10';
  return this.httpClient.get(api);    
}

в вашем компоненте:

getCoins() {
    this.appService
      .getCoins()
      .subscribe(
        data => this.coins = data.data,
        error => console.info(error)
      );
  }

  coinKeys(coins) {
    return Object.keys(coins);
}

в шаблоне:

<tr *ngFor = "let k of coinKeys(coins )">
    <td>{{ coins[k].id }}</td>
</tr>

Хорошо, я попробовал ваш пример и вижу некоторые проблемы с ним. Не уверен, чего вы пытаетесь достичь с помощью таймера, поэтому не усложняйте его. Я получаю такой ответ: { data: [], metadata: [] }

Итак, я предполагаю, что на вашей карте вам нужно сопоставить, например, этот map(res => res.data), чтобы отобразить свойство данных, например

Я переписал простой пример:

  getCoins() {
    const urlBase = "https://api.coinmarketcap.com/v2/ticker/?limit=10";
    this.http
      .get(urlBase)
      .pipe(map(res => res))
      .subscribe(res => console.info(res));
  }

Чтобы получить свойство данных, измените приведенную выше карту на .pipe(map(res => res.data)).

Чтобы избежать ошибки ts, вы также можете ввести ее: .pipe(map((res: { data: any; metadata: any }) => res.data))

Вам также понадобится дополнительное сопоставление данных, чтобы соответствовать вашему интерфейсу Coin.

Я могу больше помочь, если ты не сможешь найти способ сделать это;)

Привет, Мегаклис, спасибо за ответ. У меня есть эта ошибка: ОШИБКА в src / app / service / Coins.service.ts (34,22): ошибка TS2339: свойство «data» не существует для типа «Object».

Marcio 15.06.2018 10:08

Это потому, что вы не ввели объект данных. Попробуй так: .pipe(map((res: { data: any; metadata: any }) => res.data)) Любой надо конечно поменять на что-то более стабильное

Megaklis Vasilakis 15.06.2018 10:11

ошибка TS2339: свойство «подписаться» не существует для типа «void».

Marcio 15.06.2018 10:22

Как насчет скриншота или фрагмента?

Megaklis Vasilakis 15.06.2018 11:03

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