从 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.message
在 subscribe()
中未定义的唯一原因。那只是 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);
这太简洁了!但是,如果需要上下文,那就行不通了。
我可以使用 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.message
在 subscribe()
中未定义的唯一原因。那只是 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);
这太简洁了!但是,如果需要上下文,那就行不通了。