Pau*_*000 5 javascript operator-keyword rxjs angular
最近我需要使用 RxJS。我试图设计一个错误处理流程,但我发现了一些奇怪的语法传递方法参数:
.subscribe(
x => {
},
console.warn // <- Why does this compile, and warn 'is not 7' in debug console?
);
Run Code Online (Sandbox Code Playgroud)
https://stackblitz.com/edit/rxjs-6-5-error-handle-no-arrow-issue
,console.warn
,不喜欢,error => { console.warn(error); }
如果没有箭头函数,它仍然会将错误传递给 console.warn。为什么?
代码:
import { throwError, concat, of } from "rxjs";
import { map } from "rxjs/operators";
const result = concat(of(7), of(8));
getData(result).subscribe(
x => {
console.log("typeof(x)", typeof(x));
if (typeof(x) === 'string') {
console.log("x Error", x);
return;
}
console.log("no error", x);
},
console.warn // <- Why does this compile, and warn 'is not 7' in debug console?
);
// pretend service method
function getData(result) {
return result.pipe(
map(data => {
if (data !== 7) {
throw "is not 7";
}
return data;
})
);
}
Run Code Online (Sandbox Code Playgroud)
我试图用谷歌搜索一些关键字、js、rxjs、angular、省略箭头函数、缺少参数……但我找不到这里使用的技术。
谁能提供解释此机制的链接?
以下两个问题是相关的,但不解释行为,只说“等效”:
线
地图(this.extractTreeData)
相当于
地图(树 => this.extractTreeData(树))
首先,您需要了解您实际传递给.subscribe
函数的内容。本质上它接受三个可选参数next
,error
和complete
。每一个都是在源 observable 发出相应通知时执行的回调。
所以当你使用箭头函数时,你定义了一个就地回调函数。
sourceObservable.subscribe({
next: (value) => { },
error: (error) => { },
complete: () => { }
});
Run Code Online (Sandbox Code Playgroud)
相反,您可以单独定义函数并将其用作回调。
onNext(value) {
}
onError(error) {
}
onComplete() {
}
sourceObservable.subscribe({
next: this.onNext,
error: this.onError,
complete: this.onComplete
});
Run Code Online (Sandbox Code Playgroud)
现在这就是你所看到的。但是,您传递的是内置函数,而不是用户定义的console.warn()
函数。反过来,通知中的值将作为参数传递给回调函数。因此,您的错误中的值is not 7
作为参数发送console.warn()
,然后执行它的工作(即打印到控制台)。
但是有一个问题。如果您希望this
在回调中使用关键字来引用任何类成员变量,它会抛出一个错误,指出该变量未定义。那是因为this
在回调中指的是函数的作用域,而不是类。克服这个问题的一种方法是使用箭头函数(我们已经看到了)。或者使用bind()
函数将this
关键字的含义绑定到类。
sourceObservable.subscribe({
next: this.onNext.bind(this),
error: this.onError.bind(this),
complete: this.onComplete.bind(this)
});
Run Code Online (Sandbox Code Playgroud)
因此,例如,如果您只想拥有错误回调,则可以明确说明它并忽略其他回调。
sourceObservable.subscribe({ error: console.warn });
Run Code Online (Sandbox Code Playgroud)
现在至于你的问题“为什么函数调用中没有括号”,这里和这里讨论过。参数期望对函数的引用,函数名称表示它们的引用。
console.log
是一个函数
可以使用括号中的参数调用函数
console.log("123")
表示console.log
带参数调用函数"123"
tree => console.log(tree)
也是一个函数
它也可以用括号中的参数调用,例如。
(tree => console.log(tree))(tree)
所以一个以回调为参数的函数可以用括号中的参数调用它的回调
function example(callback) {
callback();
}
Run Code Online (Sandbox Code Playgroud)
所以如果我们传递console.log
给它example(console.log)
,它基本上运行为
function example(callback) {
console.log();
}
Run Code Online (Sandbox Code Playgroud)
如果我们传递tree => console.log(tree)
给它example(tree => console.log(tree))
,它基本上运行为
function example(callback) {
(tree => console.log(tree))();
}
Run Code Online (Sandbox Code Playgroud)
如果你理解上面的代码。现在订阅很容易理解。
function subscribe(nextCb, errorCb, completeCb) {
// ... got next data
nextCb(data);
//... got error
errorCb(error);
// completed observe
completeCb();
}
Run Code Online (Sandbox Code Playgroud)
所以你的错误回调console.log
基本上被称为console.log(error)
;
error=> console.log(error)
基本上被称为(error=> console.log(error))(error)
;
在这种情况下,结果是相同的。
在 JS 中,函数是第一类对象。当您的代码console.warn
没有括号时,您拥有对此对象的引用,但您没有调用该对象,则需要大括号console.warn()
。例如你可以这样做:
let x = console.warn;
console.log('not happened yet');
x('test');
Run Code Online (Sandbox Code Playgroud)
因此,您的代码很简单,以与传递任何其他函数完全相同的方式将console.warn
函数传递给失败的参数,例如Subscribe
Subscribe(() => {}, () => {});
Run Code Online (Sandbox Code Playgroud)
另一部分是你抛出了一个错误throw "is not 7";
。Subscribe 的错误调用的签名如下:
subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription;
Run Code Online (Sandbox Code Playgroud)
所以 的参数的error
类型是any
。因此, throw 将 an 传递Error
给错误函数处理程序。这被设置为console.warn
具有以下签名:
console.warn(obj1 [, obj2, ..., objN]);
Run Code Online (Sandbox Code Playgroud)
console.warn
本质上将其传递的任何参数转换为字符串,JS 不是强类型的,这本质上取决于类型 coercion,并记录它。的字符串throw "is not 7";
是is not 7
. 所以它记录了is not 7
.
总而言之,我想说这一切都有点神秘并且可能难以理解。这里在技术上没有任何问题,但我想说,执行以下操作更有意义:
.subscribe(
x => {
},
x => {console.warn(x);}
);
Run Code Online (Sandbox Code Playgroud)
基于“任何傻瓜都可以编写计算机可以理解的代码。优秀的程序员编写人类可以理解的代码”的原则。
归档时间: |
|
查看次数: |
687 次 |
最近记录: |