访问变量从RxJS subscribe()函数声明了一个组件

时间:2016-01-07 04:34:29

标签: javascript angular typescript rxjs arrow-functions

我可以使用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()时,我得到未定义。可以使用局部变量来解决此方案:

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相关,但为什么我无法访问this.message内的subscribe()

2 个答案:

答案 0 :(得分:34)

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

我假设您熟悉Javascript中函数调用上下文中public class test extends javax.swing.JFrame { DefaultTableModel model ; public test() { initComponents(); model = (DefaultTableModel) table.getModel(); } private void initComponents() {..} private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: Object[] a = {"insert","test"}; model.addRow(a); } 的语义(如果没有,有no shortage of explanations online) - 当然,这些语义适用于第一个片段,这就是thisthis.message内未定义的唯一原因。那只是Javascript。

因为我们谈论的是Typescript: Arrow functions是一个Typescript构造,旨在(部分)通过词法捕获subscribe()的含义来回避这些语义的尴尬,这意味着箭头函数中的this === {{1来自外部环境。

所以,如果你替换:

this

by:

this

您将获得预期的结果。

答案 1 :(得分:0)

作为@drewmoore答案的替代方法,如果您希望具有外部功能,则可以执行以下操作:

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

 ....

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

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

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

 .subscribe(dataHandler, errorHandler);

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