Ionic 3预加载数据阵列

时间:2018-03-14 18:02:38

标签: angular ionic-framework ionic3

所以这是我的问题,我通过名为" 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 的时间通过时,它会正确显示。相反,如果没有延迟,我在连接中有一个错误,即变量未定义。所以我必须找到一种在页面完全显示之前加载数据的方法。你能救我!!

谢谢。

2 个答案:

答案 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中使用的标准模式(参见文档),有助于确保在检索数据后对数据执行任何操作。