所以这是我的问题,我通过名为" TheMoviedbServicesProvider"的提供商中的电影数据库的API收集数据。并存储在模型中。 我设法收集HTML部分中的数据,但是当我尝试检索.ts文件中的信息时,我担心变量是未定义。那么我做了什么,并创建了一个按钮,并将 console.log 与它挂钩,我意识到一旦页面完全加载就可以工作。我想找到解决这个问题的方法。
这是模型中的代码
import {TheMovieDbApiConfigImage} from './themoviedbapi-config-image-model';
import {TheMovieDbApiChangeKeys} from './themoviedbapi-config-change-key-model';
export class TheMovieDbApiConfig {
change_keys: TheMovieDbApiChangeKeys[];
images: TheMovieDbApiConfigImage[];
}
和
import {BackdropSizes} from './backdropsizes';
import {LogoSizes} from './logosizes';
import {PosteSizes} from './postesizes';
import {ProfileSizes} from './profilesizes';
import {StillSizes} from './stillsizes';
export class TheMovieDbApiConfigImage {
backdrop_sizes: BackdropSizes[];
base_url: string;
logo_sizes: LogoSizes[];
poster_sizes: PosteSizes[];
profile_sizes: ProfileSizes[];
secure_base_url: string;
still_sizes: StillSizes[];
}
提供商
// Core companents
import { Http } from '@angular/http';
import { Injectable } from '@angular/core';
// RxJS
import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/map';
// Models //
import {TheMovieDbApiSearch} from '../models/search/themoviedbapi-search-model';
import {TheMovieDbApiConfig} from '../models/config/themoviedbapi-config-model';
import {TheMovieDbApiDescription} from '../models/description/themoviedbapi-desciption-model';
/*
Generated class for the ThemoviesdbServicesProvider provider.
See https://angular.io/guide/dependency-injection for more info on providers
and Angular DI.
*/
@Injectable()
export class TheMoviedbServicesProvider {
private baseUrl: string = 'https://api.themoviedb.org/3/';
private apiConf : string = 'configuration?api_key=';
private apiSearch : string = 'search/movie?api_key=';
private apiKey: string = '078016f3132847b07af647afd854c75e';
configMovie : TheMovieDbApiConfig = new TheMovieDbApiConfig();
constructor(private http: Http) {
this.resultConfig();
}
public getConfig(): Promise<TheMovieDbApiConfig> {
const url = `${this.baseUrl}${this.apiConf}${this.apiKey}`;
return this.http.get(url)
.toPromise()
.then(response => response.json() as TheMovieDbApiConfig)
.catch(error => console.log('Une erreur est survenue : ') + error)
}
public resultConfig() {
this.getConfig()
.then(configMovieFetched => {
this.configMovie = configMovieFetched;
})
}
public getUpcoming() {
const url = `https://api.themoviedb.org/3/movie/upcoming?api_key=${this.apiKey}&language=fr-FR&page=1`;
return this.http.get(url)
.toPromise()
.then(response => response.json())
.catch(error => console.log('Une erreur est survenue : ') + error)
}
public getMovies(arg, arg1, arg2, arg3): Promise<TheMovieDbApiSearch> {
const url = `${this.baseUrl}${this.apiSearch}${this.apiKey}&language=${arg}&query=${arg1}&page=${arg2}&include_adult=${arg3}`;
return this.http.get(url)
.toPromise()
.then(response => response.json() as TheMovieDbApiSearch)
.catch(error => console.log('Une erreur est survenue : ') + error)
}
public getChoice(arg, arg1): Promise<TheMovieDbApiDescription> {
const url = `${this.baseUrl}movie/${arg}?api_key=${this.apiKey}&language=${arg1}`;
return this.http.get(url)
.toPromise()
.then(response => response.json() as TheMovieDbApiDescription)
.catch(error => console.log('Une erreur est survenue : ') + error)
}
}
Prez.ts
import { Component } from '@angular/core';
import { NavController, NavParams, IonicPage } from 'ionic-angular';
import { Observable } from 'rxjs';
// Providers //
import {TheMoviedbServicesProvider} from '../../providers/themoviedb-services';
// Models //
import {TheMovieDbApiConfig} from '../../models/config/themoviedbapi-config-model';
import {TheMovieDbApiDescription} from '../../models/description/themoviedbapi-desciption-model';
/**
* Generated class for the PrezPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/
@IonicPage({
defaultHistory: ['FilmPage']
})
@Component({
selector: 'page-prez',
templateUrl: 'prez.html',
})
export class PrezPage {
choiceMovie : TheMovieDbApiDescription = new TheMovieDbApiDescription();
id: number;
langue: string;
urlJaquette: string;
manuJaquette: string;
jaquettePerso: string;
format: string;
qualite: string;
lang: string;
sousTitre: string;
release: string;
constructor(public navCtrl: NavController, public navParams: NavParams, private themoviedbServicesProvider: TheMoviedbServicesProvider) {
this.id = this.navParams.get('id');
this.langue = this.navParams.get('langue');
console.log(this.id);
this.resultGetChoice(this.id, this.langue);
this.testConsole();
if(this.choiceMovie['poster_path'] == null || '') {
this.urlJaquette = '../../assets/imgs/no-image.PNG';
} else {
this.urlJaquette = this.themoviedbServicesProvider.configMovie['images']['base_url'] + this.themoviedbServicesProvider['images']['backdrop_sizes'][0] + this.choiceMovie['poster_path'];
}
}
resultGetChoice(arg, arg1) {
this.themoviedbServicesProvider.getChoice(arg, arg1)
.then(choiceMovieFetched => {
this.choiceMovie = choiceMovieFetched;
console.log(this.choiceMovie);
})
}
testConsole() {
setTimeout(() => {
console.log(this.themoviedbServicesProvider.configMovie['images']['secure_base_url'] + this.themoviedbServicesProvider.configMovie['images']['backdrop_sizes'][0] + this.choiceMovie['poster_path']);
}, 60000)
}
button () {
console.log(this.themoviedbServicesProvider.configMovie['images']['secure_base_url'] + this.themoviedbServicesProvider.configMovie['images']['backdrop_sizes'][0] + this.choiceMovie['poster_path']);
}
}
为了简化提供程序,我创建了函数 testConsole(),这会延迟 console.log 的执行与连接,当 60000 ms 的时间通过时,它会正确显示。相反,如果没有延迟,我在连接中有一个错误,即变量未定义。所以我必须找到一种在页面完全显示之前加载数据的方法。你能救我!!
谢谢。
答案 0 :(得分:3)
是的,http是异步的。您发送请求,并在稍后的某个时间点收到回复。
在显示该路线的页面之前,您可以确保加载路线的所有数据的一种方法是,您可以使用路线解析器。
例如,这是我的一个解析器:
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { IMovie } from './movie';
import { MovieService } from './movie.service';
@Injectable()
export class MovieResolver implements Resolve<IMovie> {
constructor(private movieService: MovieService) { }
resolve(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<IMovie> {
const id = route.paramMap.get('id');
return this.movieService.getMovie(+id);
}
}
此代码从路径中检索Id,然后获取具有已定义Id的影片。所有这些都将在之前发生电影细节页面。
答案 1 :(得分:2)
这是一个替代答案,虽然我不使用Ionic而不确定如何将其转化为可以从Ionic使用的东西。
检索数据的服务方法
import { HttpClient } from '@angular/common/http';
constructor(private http: HttpClient) { }
getMovies(): Observable<IMovie[]> {
return this.http.get<IMovie[]>(this.moviesUrl);
}
请注意,它返回一个Observable,但不支持promises。
调用此方法的组件
import { HttpClient } from '@angular/common/http';
constructor(private http: HttpClient) { }
ngOnInit(): void {
this.movieService.getMovies()
.subscribe(
(movies: IMovie[]) => {
this.movies = movies;
// Any other code here
},
(error: any) => this.errorMessage = <any>error);
}
在检索代码后,您添加到传递给subscribe
方法的第一个函数的任何代码都将运行。
以上是Angular for http中使用的标准模式(参见文档),有助于确保在检索数据后对数据执行任何操作。