我正在尝试通过外部 api 从 json 数据中获取键值对,并使用 angular 和打字稿显示它。我怎样才能做到这一点?
I'm Trying to get key value pairs from json data via an external api and display it using angular and typescript. How can I achieve this?
我想从我的 api 获取结果对象中的每个键值对以显示在我的前端。即(类别、类型、难度、问题 correct_answer)我已正确设置服务和组件,我需要做的就是获取 json 并显示每一对。方法名称称为 fetchQuestions,如下所示。我能够通过简单地以与 fetchPeople 相同的方式调用它来成功获取数据,但是 json 格式不一样,所以它没有显示。然后我尝试了其他方法,但这也不起作用。我怎样才能显示这个?
People.service
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class PeopleService {
constructor(private http: HttpClient) { }
//this works like a charm as it is just a simple array
fetchPeople(): Observable <Object> {
return this.http.get('/assets/data/people.json')
}
// this doesn't work as the json from the api below is in a different
// json format. Plus I need to return all value pairs
fetchQuestions(): Observable <Object> {
return this.http.get('https://opentdb.com/api.php?
amount=10&difficulty=hard&type=boolean').map(res =>
res.json().results).subscribe(data => {
console.log(data););
}
}
API
https://opentdb.com/api.php?amount=10&difficulty=hard&type=boolean
{
"response_code": 0,
"results": [
{
"category": "Vehicles",
"type": "boolean",
"difficulty": "hard",
"question": "In 1993 Swedish car manufacturer Saab experimented
with replacing the steering wheel with a joystick in a Saab 9000.",
"correct_answer": "True",
"incorrect_answers": [
"False"
]
},
{
"category": "History",
"type": "boolean",
"difficulty": "hard",
"question": "Japan was part of the Allied Powers during World War
I.",
"correct_answer": "True",
"incorrect_answers": [
"False"
]
},
{
"category": "History",
"type": "boolean",
"difficulty": "hard",
"question": "The Kingdom of Prussia briefly held land in Estonia.",
"correct_answer": "False",
"incorrect_answers": [
"True"
]
},
{
"category": "Science: Mathematics",
"type": "boolean",
"difficulty": "hard",
"question": "The binary number "101001101" is equivalent
to the Decimal number "334"",
"correct_answer": "False",
"incorrect_answers": [
"True"
]
},
{
"category": "Entertainment: Video Games",
"type": "boolean",
"difficulty": "hard",
"question": "TF2: Sentry rocket damage falloff is calculated based
on the distance between the sentry and the enemy, not the engineer
and the enemy",
"correct_answer": "False",
"incorrect_answers": [
"True"
]
},
{
"category": "Entertainment: Video Games",
"type": "boolean",
"difficulty": "hard",
"question": "The names of Roxas's Keyblades in Kingdom Hearts
are "Oathkeeper" and "Oblivion".",
"correct_answer": "True",
"incorrect_answers": [
"False"
]
},
{
"category": "Entertainment: Music",
"type": "boolean",
"difficulty": "hard",
"question": "The band STRFKR was also briefly known as Pyramiddd.",
"correct_answer": "True",
"incorrect_answers": [
"False"
]
},
{
"category": "Entertainment: Books",
"type": "boolean",
"difficulty": "hard",
"question": "Harry Potter was born on July 31st, 1980.",
"correct_answer": "True",
"incorrect_answers": [
"False"
]
},
{
"category": "Entertainment: Japanese Anime & Manga",
"type": "boolean",
"difficulty": "hard",
"question": "Druid is a mage class in "Log Horizon".",
"correct_answer": "False",
"incorrect_answers": [
"True"
]
},
{
"category": "Geography",
"type": "boolean",
"difficulty": "hard",
"question": "The two largest ethnic groups of Belgium are Flemish and Walloon. ",
"correct_answer": "True",
"incorrect_answers": [
"False"
]
}
]
}
People.page.ts
import { Component, OnInit } from '@angular/core';
import { PeopleService } from './../../providers/people.service'
@Component({
selector: 'app-people',
templateUrl: './people.page.html',
styleUrls: ['./people.page.scss'],
})
export class PeoplePage implements OnInit {
people$;
results$;
constructor(private peopleService:PeopleService) { }
fetchPeople(){
this.people$ = this.peopleService.fetchPeople();
}
fetchQuestions(){
this.results$ = this.peopleService.fetchQuestions()
}
ngOnInit() {
}
}
People.page.html
<ion-toolbar>
<ion-title>people</ion-title>
</ion-toolbar>
</ion-header>
<ion-button (click) ="fetchPeople()" color="primary">Primary</ion-
button>
<ion-list>
<ion-item *ngFor="let person of people$ | async">{{person.name}}.
</ion-item>
</ion-list>
<ion-button (click) ="fetchQuestions()"
color="primary">Secondary</ion-button>
<ion-list>
<ion-item *ngFor="let result of results$ | async">.
{{result.category}}</ion-item>
<ion-item *ngFor="let result of results$ | async">
{{result.questions}}</ion-item>
<ion-item *ngFor="let result of results$ | async">
{{result.difficulty}}</ion-item>
<ion-item *ngFor="let result of results$ | async">
{{result.correct_answer}}</ion-item>
</ion-list>
<ion-content>
<ion-button color="primary">Primary</ion-button>
</ion-content>
HTTP GET 是一个冷可观察对象。因此,每个 async
将触发一个单独的请求。此外,您实际上并没有从 fetchQuestions()
函数返回可观察值。应删除订阅。
您还可以使用 Angular HttpParams
来设置查询参数并以 Angular 方式执行操作。
尝试以下方法
服务
import { HttpClient, HttpParams } from '@angular/common/http';
fetchQuestions(): Observable<any> {
const params = new HttpParams()
.set('amount', '10')
.set('difficulty', 'hard')
.set('type', 'boolean');
return this.http.get('https://opentdb.com/api.php', { params: params })
.pipe(map(res => res.results));
}
模板
<ng-container *ngFor="let result of results$ | async">
<ion-list>
<ion-item>{{result.category}}</ion-item>
<ion-item>{{result.question}}</ion-item>
<ion-item>{{result.difficulty}}</ion-item>
<ion-item>{{result.correct_answer}}</ion-item>
</ion-list>
</ng-container>
我也注意到了一个小字体。 result.questions
实际上应该是 result.question
.
关于热与冷可观察量的更多细节:https://blog.thoughtram.io/angular/2016/06/16/cold-vs-hot-observables.html
工作示例:Stackblitz
我想从我的 api 获取结果对象中的每个键值对以显示在我的前端。即(类别、类型、难度、问题 correct_answer)我已正确设置服务和组件,我需要做的就是获取 json 并显示每一对。方法名称称为 fetchQuestions,如下所示。我能够通过简单地以与 fetchPeople 相同的方式调用它来成功获取数据,但是 json 格式不一样,所以它没有显示。然后我尝试了其他方法,但这也不起作用。我怎样才能显示这个?
People.service
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class PeopleService {
constructor(private http: HttpClient) { }
//this works like a charm as it is just a simple array
fetchPeople(): Observable <Object> {
return this.http.get('/assets/data/people.json')
}
// this doesn't work as the json from the api below is in a different
// json format. Plus I need to return all value pairs
fetchQuestions(): Observable <Object> {
return this.http.get('https://opentdb.com/api.php?
amount=10&difficulty=hard&type=boolean').map(res =>
res.json().results).subscribe(data => {
console.log(data););
}
}
API https://opentdb.com/api.php?amount=10&difficulty=hard&type=boolean
{
"response_code": 0,
"results": [
{
"category": "Vehicles",
"type": "boolean",
"difficulty": "hard",
"question": "In 1993 Swedish car manufacturer Saab experimented
with replacing the steering wheel with a joystick in a Saab 9000.",
"correct_answer": "True",
"incorrect_answers": [
"False"
]
},
{
"category": "History",
"type": "boolean",
"difficulty": "hard",
"question": "Japan was part of the Allied Powers during World War
I.",
"correct_answer": "True",
"incorrect_answers": [
"False"
]
},
{
"category": "History",
"type": "boolean",
"difficulty": "hard",
"question": "The Kingdom of Prussia briefly held land in Estonia.",
"correct_answer": "False",
"incorrect_answers": [
"True"
]
},
{
"category": "Science: Mathematics",
"type": "boolean",
"difficulty": "hard",
"question": "The binary number "101001101" is equivalent
to the Decimal number "334"",
"correct_answer": "False",
"incorrect_answers": [
"True"
]
},
{
"category": "Entertainment: Video Games",
"type": "boolean",
"difficulty": "hard",
"question": "TF2: Sentry rocket damage falloff is calculated based
on the distance between the sentry and the enemy, not the engineer
and the enemy",
"correct_answer": "False",
"incorrect_answers": [
"True"
]
},
{
"category": "Entertainment: Video Games",
"type": "boolean",
"difficulty": "hard",
"question": "The names of Roxas's Keyblades in Kingdom Hearts
are "Oathkeeper" and "Oblivion".",
"correct_answer": "True",
"incorrect_answers": [
"False"
]
},
{
"category": "Entertainment: Music",
"type": "boolean",
"difficulty": "hard",
"question": "The band STRFKR was also briefly known as Pyramiddd.",
"correct_answer": "True",
"incorrect_answers": [
"False"
]
},
{
"category": "Entertainment: Books",
"type": "boolean",
"difficulty": "hard",
"question": "Harry Potter was born on July 31st, 1980.",
"correct_answer": "True",
"incorrect_answers": [
"False"
]
},
{
"category": "Entertainment: Japanese Anime & Manga",
"type": "boolean",
"difficulty": "hard",
"question": "Druid is a mage class in "Log Horizon".",
"correct_answer": "False",
"incorrect_answers": [
"True"
]
},
{
"category": "Geography",
"type": "boolean",
"difficulty": "hard",
"question": "The two largest ethnic groups of Belgium are Flemish and Walloon. ",
"correct_answer": "True",
"incorrect_answers": [
"False"
]
}
]
}
People.page.ts
import { Component, OnInit } from '@angular/core';
import { PeopleService } from './../../providers/people.service'
@Component({
selector: 'app-people',
templateUrl: './people.page.html',
styleUrls: ['./people.page.scss'],
})
export class PeoplePage implements OnInit {
people$;
results$;
constructor(private peopleService:PeopleService) { }
fetchPeople(){
this.people$ = this.peopleService.fetchPeople();
}
fetchQuestions(){
this.results$ = this.peopleService.fetchQuestions()
}
ngOnInit() {
}
}
People.page.html
<ion-toolbar>
<ion-title>people</ion-title>
</ion-toolbar>
</ion-header>
<ion-button (click) ="fetchPeople()" color="primary">Primary</ion-
button>
<ion-list>
<ion-item *ngFor="let person of people$ | async">{{person.name}}.
</ion-item>
</ion-list>
<ion-button (click) ="fetchQuestions()"
color="primary">Secondary</ion-button>
<ion-list>
<ion-item *ngFor="let result of results$ | async">.
{{result.category}}</ion-item>
<ion-item *ngFor="let result of results$ | async">
{{result.questions}}</ion-item>
<ion-item *ngFor="let result of results$ | async">
{{result.difficulty}}</ion-item>
<ion-item *ngFor="let result of results$ | async">
{{result.correct_answer}}</ion-item>
</ion-list>
<ion-content>
<ion-button color="primary">Primary</ion-button>
</ion-content>
HTTP GET 是一个冷可观察对象。因此,每个 async
将触发一个单独的请求。此外,您实际上并没有从 fetchQuestions()
函数返回可观察值。应删除订阅。
您还可以使用 Angular HttpParams
来设置查询参数并以 Angular 方式执行操作。
尝试以下方法
服务
import { HttpClient, HttpParams } from '@angular/common/http';
fetchQuestions(): Observable<any> {
const params = new HttpParams()
.set('amount', '10')
.set('difficulty', 'hard')
.set('type', 'boolean');
return this.http.get('https://opentdb.com/api.php', { params: params })
.pipe(map(res => res.results));
}
模板
<ng-container *ngFor="let result of results$ | async">
<ion-list>
<ion-item>{{result.category}}</ion-item>
<ion-item>{{result.question}}</ion-item>
<ion-item>{{result.difficulty}}</ion-item>
<ion-item>{{result.correct_answer}}</ion-item>
</ion-list>
</ng-container>
我也注意到了一个小字体。 result.questions
实际上应该是 result.question
.
关于热与冷可观察量的更多细节:https://blog.thoughtram.io/angular/2016/06/16/cold-vs-hot-observables.html
工作示例:Stackblitz