2016-05-26 34 views
5

Sto cercando di recuperare il contenuto di un file json locale attraverso l'uso del modulo Angular2 Http.Proprietà indefinite Angular2 e TypeScript

L'errore che sto ottenendo è di una proprietà indefinita ma penso che avrebbe dovuto essere inizializzato quando la funzione prepareCredentials è chiamata onComplete by Observable/Subscribe.

Qui segue l'errore,

TypeError: Cannot read property 'clientId' of undefined 
    at SpotifyComponent.prepareCredentials (spotify.component.ts:58) 
    at SafeSubscriber.eval [as _complete] (spotify.component.ts:38) 
    at SafeSubscriber.__tryOrUnsub (Subscriber.ts:240) 
    at SafeSubscriber.complete (Subscriber.ts:226) 
    at Subscriber._complete (Subscriber.ts:142) 
    at Subscriber.complete (Subscriber.ts:120) 
    at MapSubscriber.Subscriber._complete (Subscriber.ts:142) 
    at MapSubscriber.Subscriber.complete (Subscriber.ts:120) 
    at XMLHttpRequest.onLoad (xhr_backend.ts:67) 
    at ZoneDelegate.invokeTask (zone.js:356) 

Component,

import { Component, OnInit } from '@angular/core'; 
import { Http, Response } from '@angular/http'; 

import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/operator/map'; 
import 'rxjs/add/operator/catch'; 

import { SpotifyService } from './spotify.service'; 

@Component({ 
    moduleId: module.id, 
    selector: 'app-spotify', 
    templateUrl: 'spotify.component.html', 
    styleUrls: ['spotify.component.css'], 
    providers: [SpotifyService] 
}) 

export class SpotifyComponent implements OnInit { 
    private credentialsData: { 
    clientId: string, 
    clientSecret: string 
    }; 

    constructor(
    private http: Http, 
    private spotifyService: SpotifyService 
) { } 

    ngOnInit() { 
    if (this.spotifyService) { 
     this.http.get('../app/data/credentials.json') 
     .map(this.handleResponse) 
     .subscribe(
      this.setupCredentials, 
      this.handleError, 
     () => { this.prepareCredentials(); } 
     ); 
    } 
    } 

    private setupCredentials(subData) { 
    console.log('Setting up credentials...'); 
    this.credentialsData = { 
     clientId: <string>subData.clientId, 
     clientSecret: <string>subData.clientSecret 
    }; 
    console.log('credentials: ' + 
     JSON.stringify(this.credentialsData)); 
    console.log('credentials clientId: ' + this.credentialsData.clientId); 
    console.log('credentials clientSecret: ' + this.credentialsData.clientSecret); 
    } 

    private prepareCredentials() { 
    console.log('Preparing credentials...'); 
    this.spotifyService.prepare(
     this.credentialsData.clientId, 
     this.credentialsData.clientSecret, 
     '', 'http://localhost:4200/spotify'); 

    } 

    private handleResponse(res: Response) { 
    console.log(JSON.stringify(res.json())); 
    return res.json().spotify; 
    } 

    private handleError(error: any) { 
    let errMsg = (error.message) ? error.message : 
     error.status ? `${error.status} - ${error.statusText}` : 'Server  error'; 
    console.error(errMsg); // log to console instead 
    return Observable.throw(errMsg); 
    } 

} 

e il servizio,

import { Injectable } from '@angular/core'; 

@Injectable() 
export class SpotifyService { 
    private clientId: string; 
    private clientSecret: string; 
    private scopes: string; 
    private callbackUrl: string; 

    constructor() { } 

    wakeUpTest(): string { 
    console.log('SpotifyService is awake and initiated.'); 
    return 'SpotifyService is awake and initiated.'; 
    } 

    prepare(clientId: string, 
    clientSecret: string, 
    scopes: string, 
    callbackUrl: string): void { 
     console.log(clientId); 
    } 

    getAuthCode(): void { 
    let authUrl: string = 'https://accounts.spotify.com/authorize' + 
     '?response_type=code' + 
     '&client_id=' + this.clientId + 
     '&scope=' + encodeURIComponent(this.scopes) + 
     '&redirect_uri=' + encodeURIComponent(this.callbackUrl); 
    } 

} 

Grazie in anticipo per qualsiasi aiuto o puntatori come tutto questo è relativamente nuovo per me.

risposta

2

Suppongo che il problema si trova qui:

this.http.get('../app/data/credentials.json') 
    .map(this.handleResponse) 
    .subscribe(
    this.setupCredentials, <== 
    this.handleError, 
    () => { this.prepareCredentials(); } 
); 

Ecco predefinita comportamento JS/TS se si passa direttamente un riferimento metodo. È possibile utilizzare bind come this.setupCredentials.bind(this) o utilizzare arrow function per mantenere this:

this.http.get('../app/data/credentials.json') 
    .map(this.handleResponse) 
    .subscribe(
     (data) => this.setupCredentials(data), 
     (res) => this.handleError(res), 
    () => { this.prepareCredentials(); } 
    ); 

Spero che ti aiuta!

+0

Questo è stato fatto implicitamente. Immagino che sto truccando tutte le stampe in setupCredentials? È anche la stessa pratica fatta nella documentazione angolare, passando semplicemente la funzione per un passaggio dati implicito. –

+0

Provare a stampare 'questo' prima di' console.log ('Impostazione delle credenziali ...'); ' – yurzui

+0

Stampa' questo' mi ha dato una stampa di un oggetto 'SafeSubscriber', [come tale] (http: // pastebin. com/M4GDSZv1). –

Problemi correlati