Node.js程序不会在“try{}”之后运行“finally{}”块并以代码0退出
今天,我在Node.js中用RxJS编写了一些代码,得到了非常好的结果:程序运行Node.js程序不会在“try{}”之后运行“finally{}”块并以代码0退出,node.js,rxjs,Node.js,Rxjs,今天,我在Node.js中用RxJS编写了一些代码,得到了非常好的结果:程序运行try{}块,但根本没有运行finally{}块,在try{}块中使用代码0退出 缩短代码后,为了重现此问题,步骤如下: 首先创建一个名为subject的BehaviorSubject 调用subject.asObservable().share()并获取名为obs 调用obs.subscribe() 调用等待obs.first().toPromise() 最后,程序执行一个非常有线的行为:退出try{}块,而不在下
try{}
块,但根本没有运行finally{}
块,在try{}
块中使用代码0退出
缩短代码后,为了重现此问题,步骤如下:
subject
的BehaviorSubject
subject.asObservable().share()
并获取名为obs
等待obs.first().toPromise()
try{}
块,而不在下面的finally{}
块中运行代码
复制它的TypeScript代码如下:运行它,您将得到一行输出:1。在尝试之前
,这不是预期的
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()
更新
通过@martin的回答,我意识到这就是Node.js的行为
我编写了一个可复制的程序来演示如何在try{}
块中退出Node.js,并使用代码0退出,而不运行finally{}
块,这非常简单:等待一个永不解决的承诺
async function main() {
try {
await new Promise(r => console.log('IN TRY BLOCK'))
} finally {
console.log('IN FINALLY BLOCK')
}
}
main()
上述程序将仅在TRY块中输出,并以代码0退出,而在FINALLY块
中根本不输出
对于那些觉得这也很奇怪的读者,我还为node在上打开了一个问题,你想实现什么?为什么你要创造和观察,然后立即将其转化为承诺
如果你需要处理“事件流”,你可以创建一个可观察的
这是一个使用观察值的例子,不知何故是从你的观察值中派生出来的
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();
从'rxjs/Rx'导入{BehaviorSubject}
const subject=新行为主体(-1)
const obs=subject.asObservable().share();
console.log('1.在子描述之前');
obs
.订阅(
aNumber=>console.log('2.处理子描述',aNumber),
err=>console.error(err),
()=>console.log('3.COMPLETED OBSERVABLE')
)
主题。下一个(0);
主题。下一(1);
主题。下一(2);
subject.complete();
由于您使用的运算符,这实际上是正确的行为
您正在创建一个BehaviorSubject(-1)
,它向每个新订户发出-1
。然后您就有了share()
,该始终只保留一个对其源可观察订阅的
这里是最重要的。当您使用obs.subscribe()
时,它使share
订阅其源(subject
事实上),该源立即发出-1
,但该值不会打印在任何地方,因为您使用了带有.subscribe()
的空订阅服务器
然后你用wait obs.first()
从未解决,因此等待
将永远等待
但是,如果使用而不是obs.subscribe()
,例如:
obs.take(1).subscribe(console.log);
请参阅控制台输出:
。。。您将看到预期的输出,因为take(1)
在收到-1
后立即取消订阅,然后第二个订阅者toPromise()
使share()
再次订阅subject
,发出-1
,承诺成功解决。如果.toPromise()
将永远无法解决,程序应该永远在那里等待。但是,结果是程序以代码0退出。请运行代码,您将发现它立即退出。这是两件不同的事情。main
方法是async
,因此它只返回一个承诺,并继续执行。然而,承诺仍然没有得到解决,wait
将永远等待。您可以在这里看到,wait
之后的任何内容都不会执行:。当程序结束时,表示偶数循环中没有更多的事件(在演示中是这样),但这与本例无关。您能解释一下为什么不执行这段代码吗console.log('2.AFTER TRY')
因为它是在前一个承诺由于wait
而得到解决之后执行的,这是因为setTimeout
创建了另一个安排在60秒内的事件。在您的演示中,事件循环中没有更多的事件,因此结束。我将代码缩短,以证明它将立即退出,而无需在finally{}
块中运行代码,这是非常有线的。
obs.take(1).subscribe(console.log);