从 RxJS subscribe() 函数访问声明为组件的变量

Access variables declared a component from a RxJS subscribe() function

我可以使用 this.variable 访问组件任何部分的变量,除了像 subscribe()catch() 这样的 RxJS 函数内部。

在下面的示例中,我想在 运行 处理一个进程后打印一条消息:

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

当我 运行 doSomething() 时,我得到 undefined。这种情况可以使用局部变量来解决:

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

我想这与this有关,但是,为什么我无法访问subscribe()中的this.message

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

我假设您熟悉 Javascript 中函数调用上下文中 this 的语义(如果不是,则有 no shortage of explanations online)- 这些语义适用于第一个片段,当然,这是 this.messagesubscribe() 中未定义的唯一原因。那只是 Javascript。

既然我们在谈论打字稿: Arrow functions 是一个 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'
    });

您将获得预期的结果。

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

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

 ....

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

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

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

 .subscribe(dataHandler, errorHandler);

这太简洁了!但是,如果需要上下文,那就行不通了。