【问题标题】:Property undefined Angular2 and TypeScript属性未定义 Angular2 和 TypeScript
【发布时间】:2016-05-27 02:24:03
【问题描述】:

我正在尝试通过使用 Angular2 模块 Http 来检索本地 json 文件的内容。

我得到的错误是一个未定义的属性,但我认为它应该在 Observable/Subscribe 调用 prepareCredentials 函数时被初始化。

以下是错误,

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)

组件,

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);
  }

}

和服务,

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);
  }

}

在此先感谢您的帮助或指点,因为所有这些对我来说都是相对较新的。

【问题讨论】:

    标签: typescript angular undefined


    【解决方案1】:

    我想你的问题出在这里:

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

    如果您直接传递方法引用,那是默认的 JS/TS 行为。您可以使用 this.setupCredentials.bind(this) 之类的绑定,也可以使用 arrow function 保留 this

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

    希望对你有帮助!

    【讨论】:

    • 这是隐式完成的,我会假设我正在设置 setupCredentials 中的所有打印输出?这也是 Angular 文档中的相同做法,仅传递隐式数据传递的函数。
    • console.log('Setting up credentials...');之前尝试打印this
    • Printing this 给了我一个 SafeSubscriber 对象 like so 的打印输出。
    • 我将不得不原谅自己,您提供的解决方案实际上解决了我的问题。这是否与对象的实例化有关?由于 Angular2 文档按照我最初的方式进行操作,我的情况是不是一个特例?无论如何,感谢@yurzui 的帮助。
    • 我可以看到链接到使用这种做法的文档示例的链接吗?
    猜你喜欢
    • 1970-01-01
    • 2017-09-24
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-29
    • 2018-04-10
    • 1970-01-01
    相关资源
    最近更新 更多