角“无法读取未定义的属性'subscribe'”

Merianos Nikos:

在开始提出问题之前,我想告诉您我已经进行了大量研究,并且我找不到找到出现此错误的解决方案(解释)。

还请注意,我对Angular完全陌生,我才刚刚开始学习它的工作原理。

因此,我所遇到的问题是我在此问题的标题中输入的内容。

我尝试做的是根据我在Udemy上购买的课程,使用Firebase构建登录系统。

我使用的代码如下:

身份验证服务

import {Injectable} from '@angular/core';
import * as firebase from 'firebase';

@Injectable ()
export class AuthService {
    token: string;

    // ...

    singInUser ( email: string, password: string ) {
        // login process here ...
    }

    // Responsible to retrieve the authenticated user token
    getToken () {   
        return firebase
            .auth ()
            .currentUser
            .getIdToken ();
    }
}

数据存储服务

// ... Dependencies here
@Injectable ()
export class DataStorageService {
    private recipeEndPoint: string = 'https://my-unique-id.firebaseio.com/recipes.json';
    private recipeSubscription: Observable<any> = new Observable();

    constructor ( private http: Http,
                  private recipes: RecipeService,
                  private authService: AuthService ) {}

    // other functionality ...

    getRecipes () {
        const token = this.authService.getToken ();

        token.then (
            ( token: string ) => {
                this.recipeSubscription = this.http.get ( this.recipeEndPoint + '?auth=' + token ).map (
                    ( data: Response ) => {
                        return data.json ();
                    }
                );

                // THIS PARTICULAR CODE WORKS AS EXPECTED
                // WITH NO ISSUES
                this.recipeSubscription.subscribe (
                    ( data: Response ) => {
                        console.log ( 'Data response: ', data );
                    },
                    ( error ) => {
                        console.log ( 'Error: ' + error );
                    }
                )
            }
        );

        // This is supposed to return an Observable to the caller
        return this.recipeSubscription;
    }
}

header.component.ts

// Dependencies here ...

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
  constructor(private dataStorage: DataStorageService, private recipeService: RecipeService) { }

  // Other Code Here ...

  onFetchData() {
    let recipeSubscription = this.dataStorage.getRecipes();

    // THIS RETURNS TRUE
    console.log(recipeSubscription instanceof Observable);

    // THIS LINE THEN RETURNS THE MESSAGE:
    // ERROR TypeError: Cannot read property 'subscribe' of undefined
    recipeSubscription.subscribe();

    // IF I COMMENT OUT THE PREVIOUS LINE
    setTimeout(
      () => {
        // THIS RETURNS TRUE
        console.log(recipeSubscription instanceof Observable);
      },
      500
    );

    setTimeout(
      () => {
        // AS WELL THIS ONE RETURNS TRUE
        console.log(recipeSubscription instanceof Observable);
      },
      1000
    );

    setTimeout(
      () => {
        // AS WELL THIS ONE RETURNS TRUE
        console.log(recipeSubscription instanceof Observable);
      },
      1500
    );
  }
}

因此,不幸的是,我看不到这段代码有什么问题。谁能发现我做错了什么?

注意: 我删除了部分代码,只是为了使代码片段更具可读性。如果您需要其他任何部分,请随时问我,我将在这里提供。

更新#1

这就是它的样子 header.component.html

<nav class="navbar navbar-default">
    <div class="container-fluid">
        <div class="navbar-header">Logo Here</div>

        <div class="navbar-default">
            <ul class="nav navbar-nav">
                <!-- Left Navigation Options -->
            </ul>
            <ul class="nav navbar-nav navbar-right">
                <!-- Right Navigation Options -->
                <li class="dropdown" appDropdown>
                    <a routerLink="/" class="dropdown-toggle" role="button">Manage <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li>
                            <a style="cursor: pointer;" (click)="onSaveData()">Save Data</a>
                        </li>
                        <li>
                            <!-- Here is where I call the onFetchData method -->
                            <a style="cursor: pointer;" (click)="onFetchData()">Fetch Data</a>
                        </li>
                    </ul>
                </li>
            </ul>
        </div>
    </div>
</nav>
AngularChef:

问题似乎是代码执行的顺序,更具体地说是getRecipes()方法:

// Numbers indicate the execution order

getRecipes () {
    const token = this.authService.getToken ();

    // 1. You call a promise, which will take a while to execute...
    token.then (
        ( token: string ) => {
            // 3. Finally, this bit gets executed, but only when the promise resolves.
            this.recipeSubscription = ...
        }
    );

    // 2. Then, you return a variable that hasn't been assigned yet,
    // due to the async nature of the promise.
    return this.recipeSubscription;
}

解决方案是您的getRecipes ()方法不应该订阅。它应该返回Promise或Observable

像这样:

getRecipes() {
    // Convert the initial promise into an observable
    // so can you use operators like map(), mergeMap()... to transform it.
    const tokenObs = Observable.fromPromise(this.authService.getToken());

    // Merge the token observable into an HTTP observable
    // and return the JSON data from the response.
    return tokenObs
      .mergeMap(token => this.http.get('XXX?auth=' + token))
      .map(resp => resp.json());
}

然后,调用代码HeaderComponent变为:

const recipeObs = this.dataStorage.getRecipes();
recipesObs.subcribe(jsonData => {
  // Use the JSON data from the HTTP response
});

几点评论:

  • 您需要显式导入代码中使用的RxJS运算符。如果按照我的示例,则需要在开始时添加以下导入:
import 'rxjs/add/observable/fromPromise';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
  • 您永远不要订阅创建可观察对象的方法。就您而言,请勿订阅getRecipes()始终在最后一分钟订阅。您可以多次订阅相同的可观察对象,但是请注意,每个订阅都会重新执行可观察对象(对于http请求,这意味着您多次运行该请求;不理想...)。
  • 调用变量不是一个好主意,recipeSubscription因为它包含一个Observable,而不是一个Subscription订阅即subscribe()返回。换句话说:const subscription = observable.subscribe()
  • 我看到您正在直接使用Firebase SDK。您知道AngularFire库吗?

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

业力TypeError“无法读取未定义的属性'subscribe'”

Angular无法读取未定义的属性“ subscribe”

Angular 9 TypeError:无法读取未定义的属性“ subscribe”

Angular 2无法读取未定义类型的属性“ subscribe”:无法读取未定义的属性“ subscribe”

Angular2-无法读取嵌套调用中未定义的属性“ subscribe”

例外:TypeError:升级后无法读取未定义的属性“ subscribe”

无法读取Ionic 4(Angular 8)上未定义的属性“ subscribe”

运行npm测试(Angular 2单元测试)后无法读取未定义的属性“ subscribe”

ng2-translate:无法读取TranslatePipe.transform中未定义的属性“ subscribe”

单元测试中的角度“无法读取未定义的属性'subscribe'”

Angular 4单元测试错误“ TypeError:无法读取未定义的属性'subscribe'”

角度组件测试错误:TypeError无法读取未定义的属性“ subscribe”

设置MdPaginatorIntl提供程序后,我得到“无法读取未定义的属性'subscribe'”

为什么在运行测试时出现“失败:无法读取未定义的属性'subscribe'”?

错误TypeError:无法读取POST HTTP调用上未定义的属性“ subscribe”-角度[8]

角2 .subscribe()返回未定义

Angular2-单元测试可观察到的错误“无法读取未定义的属性'subscribe'”

angular2指令“无法读取未定义的属性” subscribe”,带有输出元数据

Ionic v5/Angular 8:HttpClient.get().subscribe() 返回 TypeError:无法读取未定义的属性“句柄”

在subscribe()中设置后,角组件属性莫名其妙地保持“未定义”

使用Internet Explorer的react-redux trySubscribe中的错误(无法获得未定义的属性“ subscribe”)

角“ ERROR TypeError:无法读取未定义的属性”匹配“

角4:无法读取未定义的属性“ http”

角 | 无法读取未定义的属性“XXX”

角2:无法读取未定义的属性“验证器”

角6:TypeError:无法读取未定义的属性“无效”?

无法读取未定义的属性(读取 *)

Rx.js,使用未定义的方式调用Subscribe

更改 observables 时,subscribe 内的 Observable 值未定义