TypeError: Cannot read property '_router' of null in NativeScript

TypeError: Cannot read property '_router' of null in NativeScript

我正在使用 NativeScript+AngularJS2+TypeScript 开发 android 应用程序。按照他们的文档 - http://docs.nativescript.org/angular/tutorial/ng-chapter-0 .

成功登录后用户需要重定向到 List 页面时卡住了。现在关注他们的路由部分 - http://docs.nativescript.org/angular/tutorial/ng-chapter-3#35-routing

根据他们的文件做了一切。这是我的代码 -

app.component.ts

import {ListPage} from "./pages/list/list.component";
import {Component} from "@angular/core";
import {RouteConfig} from "@angular/router-deprecated";
import {NS_ROUTER_DIRECTIVES, NS_ROUTER_PROVIDERS} from "nativescript-angular/router";
import {LoginPage} from "./pages/login/login.component";

@Component({
  selector: "main",
  directives: [NS_ROUTER_DIRECTIVES],
  providers: [NS_ROUTER_PROVIDERS],
  template: "<page-router-outlet></page-router-outlet>"
})
@RouteConfig([
  { path: "/Login", component: LoginPage, name: "Login", useAsDefault: true },
  { path: "/List", component: ListPage, name: "List" }
])
export class AppComponent {}

user.service.ts

import {Injectable} from "@angular/core";
import {User} from "./user";
import {ConfigService} from "../config";
import firebase = require("nativescript-plugin-firebase");

@Injectable()
export class UserService {

    register(user: User, config: ConfigService) {

        console.log('Email entered : '+user.email);
        console.log('Password entered : '+user.password);
        console.log("API url going to use is : "+config.apiUrl);

        firebase.init(<any>{
            persist: true, // Allow disk persistence. Default false.
            url: config.apiUrl
        }).then(
            function (instance) {
                console.log("firebase.init done");
            },
            function (error) {
                console.log("firebase.init error: " + error);
            }
        );

        return firebase.createUser({
            email: user.email,
            password: user.password
          }).then(
              function (response) {
                console.log(response);
                return response;
              }
          )

    }

    login(user: User, config: ConfigService) {

        firebase.init({
            persist: true, // Allow disk persistence. Default false.
            url: config.apiUrl
        }).then(
            function (instance) {
                console.log("firebase.init done");
            },
            function (error) {
                console.log("firebase.init error: " + error);
            }
        );

        return firebase.login({
            type: firebase.LoginType.PASSWORD,
            email: 'eddyverbruggen@gmail.com',
            password: 'firebase'
          }).then(
              function (response) {
                console.log(response);
                return response;
              }
          )

    }

}

login.component.ts

import {Router} from "@angular/router-deprecated";
import {Component} from "@angular/core";
import {User} from "../../shared/user/user";
import {UserService} from "../../shared/user/user.service";
import {ConfigService} from "../../shared/config";
import {HTTP_PROVIDERS} from "@angular/http";
import firebase = require("nativescript-plugin-firebase");

@Component({
    selector: "my-app",
    providers: [UserService, HTTP_PROVIDERS,ConfigService],
    templateUrl: "pages/login/login.html",
    styleUrls: ["pages/login/login-common.css", "pages/login/login.css"]
})

export class LoginPage {
    user: User;
    isLoggingIn = true;
    config:any;

    constructor(private _router: Router, private _userService: UserService) {
        this.user = new User();
        this.config = new ConfigService();
    }

    submit() {
        if (this.isLoggingIn) {
            this.login();
        } else {
            this.signUp();
        }
    }


    login() {

        var result = this._userService.login(this.user,this.config);

        result.then(
            function (result) {
                console.log("Login Successs");
                // the result object has these properties: uid, provider, expiresAtUnixEpochSeconds, profileImageURL, token
                var response = JSON.stringify(result);
                console.log('Login Response : '+response);

                // Route to list page
                this._router.navigate(["List"]);
            },
            function (errorMessage) {
                console.log("Login Error");
                console.log(errorMessage);
            }
        );
    }

    signUp() {
        var result = this._userService.register(this.user,this.config);

        result.then(
            function (result) {
                // dialogs.alert({
                //  title: "User created",
                //  message: "userid: " + result.key,
                //  okButtonText: "Nice!"
                // })
                console.log('User Object Info : '+JSON.stringify(result));
                console.log('User Created with user id - '+result.key);
                alert("Your account was successfully created.");

                this.toggleDisplay();
            },
            function (errorMessage) {
                // dialogs.alert({
                //  title: "No user created",
                //  message: errorMessage,
                //  okButtonText: "OK, got it"
                // })
                console.log('No user created. Got error message insted - '+errorMessage);
                alert("Unfortunately we were unable to create your account.")
            }
        );


    }

    toggleDisplay() {
        this.isLoggingIn = !this.isLoggingIn;
    }
}

除了从文件 this._router.navigate(["List"]); 执行 login.component.ts 时一切正常,我收到以下错误

JS: EXCEPTION: Error: Uncaught (in promise): TypeError: Cannot read property '_router' of null

无法理解错误到底是什么。

此致

我预计此问题与上下文范围问题有关。我认为您应该先尝试捕获示波器,然后再进入您的示波器。我通常将其存储在一个名为 that 的变量中,请参见下文(并查看评论):

login() {

    var result = this._userService.login(this.user,this.config);
    var that = this; //store the current context 
    result.then(
        function (result) { //context (this has changed)
            console.log("Login Successs");
            // the result object has these properties: uid, provider, expiresAtUnixEpochSeconds, profileImageURL, token
            var response = JSON.stringify(result);
            console.log('Login Response : '+response);

            // Route to list page
            that._router.navigate(["List"]); //reference _router from the original scope
        },
        function (errorMessage) {
            console.log("Login Error");
            console.log(errorMessage);
        }
    );
}

是的,您可以像 George Edwards 指出的那样动态绑定 this。另一种选择是使用箭头函数,它允许您在函数内保留调用者的范围,这样您就不需要总是记住写 var that = this.

login() {

    var result = this._userService.login(this.user,this.config);
    result.then(
        // Within the arrow function 'this' now refers to the lexical context rather than changing depending upon how the function is called.
        (result) => {
            console.log("Login Successs");
            // the result object has these properties: uid, provider, expiresAtUnixEpochSeconds, profileImageURL, token
            var response = JSON.stringify(result);
            console.log('Login Response : '+response);

            // Route to list page
            this._router.navigate(["List"]); //reference _router from the original scope
        },
        // Arguably clearer
        (errorMessage) => {
            console.log("Login Error");
            console.log(errorMessage);
        }
    );
}