可观察订阅内不可用的角度局部范围

时间:2017-05-12 14:47:44

标签: angular rxjs angular2-services

我一直在努力解决这个问题,尝试了很多解决方案。

在我的订阅中,我无法访问ChangeDetectorRef或NgZone来强制更新我的范围。

为什么没有任何作用?是否有任何其他Angular感知的HTTP请求方式?

登录组件

import {ChangeDetectionStrategy, ChangeDetectorRef, Component, NgZone, OnInit} from '@angular/core';
import {LoginService} from './login.service';
import {Observable} from 'rxjs/Observable';

@Component({
    selector: 'app-login',
    templateUrl: './login.component.html',
    styleUrls: ['./login.component.css'],
    providers: [LoginService]
})
export class LoginComponent implements OnInit {
    zone: NgZone;
    username = '';
    password = '';
    showerror = false;
    errormsg = '';
    rs = {};
    results: any;


    constructor(private _loginService: LoginService, private ref: ChangeDetectorRef) {

    }

    refr = function () {
        console.log('refresh');
        console.log(this.errormsg); // is empty even after HTTP call
        this.ref.markForCheck();
        console.log(this.results);
    };

    login = function () {
        console.log(this.username, this.password);

        this._loginService.login(this.username, this.password).subscribe(function (data) {

            console.log('log me in');
            console.log(data); // the correct data is logged here
            this.errormsg = 'Invalid Username and Password'; // the text is never updated
            this.zone.run(); // zone has no method run
            this.ref.markForCheck(); // ref has no method markForCheck
        });

        // this.results = this._loginService.login(this.username, this.password);
        // this.results.subscribe(rs => this.rs = rs);   
    };

    ngOnInit() {

    }

}

登录服务

import {Injectable} from '@angular/core';
import {CONFIG} from '../config';
import {Http, Response} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';

const loginUrl: string = CONFIG.apiserv + 'api.login.php';

@Injectable()
export class LoginService {
    private http;
    constructor(http: Http) {
        this.http = http;
    }

    login = function (username, password): Observable<Response> {
        console.log('login clicked');
        let url = new URLSearchParams();
        url.append('username', username);
        url.append('password', password);
        const fullurl = loginUrl + '?' + url.toString();

        return this.http.get(fullurl)
            .map((response: Response) => response.json())
            .do(data => console.log('All: ' + JSON.stringify(data)))
            .catch(this.handleError);
    };
    handleError = function (error: Response) {
        console.log(error);
        return Observable.throw(error.json().error || 'Server error');
    };
}

2 个答案:

答案 0 :(得分:3)

由于您使用的是this,因此您应该使用arrow function

this._loginService.login(this.username, this.password).subscribe(data => {

        console.log('log me in');
        console.log(data); // the correct data is logged here
        this.errormsg = 'Invalid Username and Password'; // the text is never updated
        this.zone.run(); 
        this.ref.markForCheck(); 
    });

答案 1 :(得分:3)

如果要将this绑定到新创建的范围,则需要使用=>

this._loginService.login(this.username, this.password).subscribe(data => {

请参阅:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

否则,您可以将this分配给变量,但如果您使用的是TypeScript或ES6则不需要。

var that = this;
this._loginService.login(this.username, this.password).subscribe(function (data) {
    that.zone.run();
    ...