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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34647449/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:11:49  来源:igfitidea点击:

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

javascriptangulartypescriptrxjsarrow-functions

提问by Haoliang Yu

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

我可以使用this.variable访问组件任何部分中的变量,除了像subscribe()或 之类的 RxJS 函数内部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:

当我运行时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);
        });
    }
}

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

我想这与this,但是,为什么我无法访问this.message内部subscribe()

回答by drew moore

This has nothing to do with rx or angular, and everything to do with Javascript and Typescript.

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

I assume you're familiar with the semantics of thisin the context of function invocations in Javascript (if not, there are no shortage of explanations online) - those semantics apply in the first snippet, of course, and that's the only reason this.messageis undefined inside subscribe()there. That's just Javascript.

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

Since we're talking about Typescript: Arrow functionsare a Typescript construct intended (in part) to sidestep the awkwardness of these semantics by lexically capturing the meaning of this, meaning that thisinside an arrow function === thisfrom the outer context.

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

So, if you replace:

所以,如果你更换:

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

by:

经过:

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

You'll get your expected result.

你会得到你预期的结果。

回答by HankCa

As an alternative to @drewmoore's answer, if you wish to have external functions you can do:

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

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

 ....

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

By externalising the errorHandlerfunction, it can be used in multiple places (ie. subscriptions). By having as (fat) arrow functions your code will capture the 'this' context (as discussed in @Drewmoore's answer).

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

What is lacking is the ability to write the following and have handled like an arrow function. The following works and passes the argument implicitly. Unfortunately AFAIK you cannot capture the thiscontext (perhaps use bindto achieve this, though that makes the code more verbose overall).

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

 .subscribe(dataHandler, errorHandler);

This is soooo succinct! But alas won't work if the context is required.

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