今天我在Node.js中用RxJS编写了一些代码并得到了非常有线的结果:程序运行try{}
块,但根本没有运行finally{}
块,退出代码0在try{}
区块内。
使我的代码简短后,为了重现这个问题,步骤是:
BehaviorSubject
subject
subject.asObservable().share()
并获取名为obs
obs.subscribe()
await obs.first().toPromise()
然后,最后,程序执行非常有线的行为:退出try {}
块而不运行以下finally {}
块内的代码。
重现它的TypeScript代码如下:运行它,然后你会得到一行输出:1. BEFORE TRY
,这是不期望的!
import {
BehaviorSubject,
} from 'rxjs/Rx'
async function main() {
const subject = new BehaviorSubject<number>(-1)
const obs = subject.asObservable().share()
/**
* if comment the following line, this program will output right as the following three lines:
*
* 1. BEFORE TRY
* 2. AFTER TRY
* 3. FINALLY
*
* otherwise, the output will only be:
*
* 1. BEFORE TRY
*
* very wired!
*
*/
obs.subscribe()
try {
console.log('1. BEFORE TRY')
await obs.first().toPromise()
console.log('2. AFTER TRY')
} finally {
console.log('3. FINALLY')
}
}
main()
我的问题是: Node.js如何退出try{}
块而不运行finally{}
块,退出代码为0?
有没有人有想法?
ENV:
$ uname -a
Darwin zixia-pro.lan 16.7.0 Darwin Kernel Version 16.7.0: Tue Jan 30 11:27:06 PST 2018; root:xnu-3789.73.11~1/RELEASE_X86_64 x86_64
$ node --version
v9.8.0
$ grep rxjs ../package.json
"rxjs": "^5.5.6"
根据@martin的回答,我意识到这是Node.js的行为。
我编写了一个可重现的程序来演示如何在try{}
块中退出Node.js并退出代码0而不运行finally{}
块,这非常简单:等待永不解决的Promise
async function main() {
try {
await new Promise(r => console.log('IN TRY BLOCK'))
} finally {
console.log('IN FINALLY BLOCK')
}
}
main()
上述程序只输出IN TRY BLOCK
并退出代码0,根本不输出IN FINALLY BLOCK
。
对于认为这也很奇怪的读者,我也在https://github.com/nodejs/node/issues/19929
为节点打开了一个问题答案 0 :(得分:1)
由于您使用的运算符,这实际上是正确的行为。
您正在为每个新订阅者创建BehaviorSubject(-1)
-1
。然后你有share()
始终只保留一个订阅源Observable 。
这是最重要的事情。当您使用obs.subscribe()
时,它会share
订阅其来源(实际上为subject
),该来源会立即发出-1
,但由于您使用了该值,因此无法在任何位置打印使用.subscribe()
的空订阅者。
然后,您使用await obs.first().toPromise()
创建了另一个订阅者,但仍然是订阅的第一个订阅者,因此share()
维护此单一订阅subject
所以来源BehaviorSubject
永远不会再发出这意味着.toPromise()
中的承诺永远不会被解决,所以await
会一直等待。
但是,如果您使用而不是obs.subscribe()
,例如:
obs.take(1).subscribe(console.log);
请参阅控制台输出:https://stackblitz.com/edit/rxjs5-pev27v?file=index.ts
...您会看到预期的输出,因为take(1)
在收到-1
后取消订阅,然后第二个订阅者toPromise()
让share()
订阅{ {1}}再次发出subject
并且Promise已成功解决。
答案 1 :(得分:0)
你想要达到什么目的?为什么要创建和Observable然后立即将其转换为Promise?
如果您需要处理&#34;事件流&#34;,您可以创建一个Observable。
这是一个使用Observables的例子,从你的
以某种方式派生import {BehaviorSubject} from 'rxjs/Rx'
const subject = new BehaviorSubject<number>(-1)
const obs = subject.asObservable().share();
console.log('1. BEFORE SUBCRIPTION');
obs
.subscribe(
aNumber => console.log('2. PROCESSING SUBCRIPTION', aNumber),
err => console.error(err),
() => console.log('3. COMPLETED OBSERVABLE')
)
subject.next(0);
subject.next(1);
subject.next(2);
subject.complete();