15

I am able to use this.variable to access variables in any part of the component, except inside RxJS functions like subscribe() or catch().

In the example below, I want to print a message after running a process:

import {Component, View} from 'angular2/core';

@Component({
    selector: 'navigator'
})
@View({
    template: './app.component.html',
    styles: ['./app.component.css']
})
export class AppComponent {
    message: string;

    constructor() {
        this.message = 'success';
    }

    doSomething() {
        runTheProcess()
        .subscribe(function(location) {
            console.log(this.message);
        });
    }
}

When I run doSomething(), I get undefined. This scenario can be solved using a local variable:

import {Component, View} from 'angular2/core';

@Component({
    selector: 'navigator'
})
@View({
    template: './app.component.html',
    styles: ['./app.component.css']
})
export class AppComponent {
    message: string;

    constructor() {
        this.message = 'success';
    }

    doSomething() {

        // assign it to a local variable
        let message = this.message;

        runTheProcess()
        .subscribe(function(location) {
            console.log(message);
        });
    }
}

I suppose this is related to the this, however, why I can't access the this.message inside the subscribe()?

4

2 回答 2

39

这与 rx 或 angular 无关,与 Javascript 和 Typescript 无关。

我假设您熟悉thisJavascript 中函数调用上下文中的语义(如果不熟悉,在线上不乏解释) - 当然,这些语义适用于第一个片段,这是唯一的原因this.message是内部未定义subscribe()那里。那只是Javascript。

由于我们在谈论 Typescript: 箭头函数是一种 Typescript 构造,旨在(部分)通过词汇捕获 的含义来回避这些语义的尴尬,这this意味着this箭头函数内部 ===this来自外部上下文。

所以,如果你更换:

.subscribe(function(location) {
        //this != this from outer context 
        console.log(this.message); //prints 'undefined'
    });

经过:

.subscribe((location) => {
     //this == this from the outer context 
        console.log(this.message); //prints 'success'
    });

你会得到你预期的结果。

于 2016-01-07T04:44:44.513 回答
2

作为@drewmoore 答案的替代方案,如果您希望拥有外部功能,您可以这样做:

 .subscribe((location) => dataHandler(location), (error) => errorHandler(error));

 ....

 const dataHandler = (location) => {
     ...
 }

通过将函数外部errorHandler化,它可以在多个地方使用(即订阅)。通过使用 as (fat) 箭头函数,您的代码将捕获“this”上下文(如@Drewmoore 的回答中所述)。

缺少的是编写以下内容并像箭头函数一样处理的能力。以下工作并隐式传递参数。不幸的是,AFAIK 您无法捕获this上下文(也许可以bind用来实现这一点,尽管这会使代码总体上更加冗长)。

 .subscribe(dataHandler, errorHandler);

这太简洁了!但是,如果需要上下文,那将无法正常工作。

于 2019-04-17T06:46:40.460 回答