web-dev-qa-db-ja.com

RxJS subscribe()関数からコンポーネントを宣言したアクセス変数

_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()を実行すると、-ndefinedが表示されます。このシナリオは、ローカル変数を使用して解決できます。

_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_にアクセスできないのはなぜですか?

13
Haoliang Yu

これはrxやangularとは何の関係もありませんし、JavascriptとTypeScriptとはすべて関係があります。

私はあなたがJavaScriptの関数呼び出しのコンテキストでthisのセマンティクスに精通していることを前提としています(そうでない場合、 オンラインで説明が不足していません )-もちろん、これらのセマンティクスは最初のスニペットに適用され、それが_this.message_がsubscribe() there内で定義されていない唯一の理由です。それは単なる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'
    });
_

期待どおりの結果が得られます。

36
drew moore

@drewmooreの答えの代わりに、外部関数が必要な場合は、次のようにできます。

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

 ....

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

errorHandler関数を外部化することで、複数の場所(サブスクリプションなど)で使用できます。 as(fat)矢印関数を使用することで、コードは「this」コンテキストをキャプチャします(@Drewmooreの回答で説明)。

不足しているのは、以下を記述し、矢印関数のように処理する機能です。以下は機能し、暗黙的に引数を渡します。残念ながら、私の知る限り、thisコンテキストをキャプチャすることはできません(これを実現するためにbindを使用することもできますが、コード全体がより冗長になります)。

 .subscribe(dataHandler, errorHandler);

これはすごく簡潔です!しかし、状況が必要な場合、悲しいかな動作しません。

1
HankCa