rxjs 中的 .toPromise() 和 lastValueFrom()

use*_*er1 7 javascript promise rxjs

我有这个可观察的

createMyRecord(): Observable<myRecord> {
        return of(TEMPLATE_DB).pipe(
            mergeMap((template) => doTask(template)),
            mergeMap(() => EMPTY)
        );
    }
Run Code Online (Sandbox Code Playgroud)

我用它来称呼它

await createMyRecord().toPromise();
Run Code Online (Sandbox Code Playgroud)

.toPromise() 已弃用,所以我想用 lastValueFrom() 更改调用:

await lastValueFrom(createMyRecord());
Run Code Online (Sandbox Code Playgroud)

但我收到以下错误:

EmptyError
no elements in sequence
Run Code Online (Sandbox Code Playgroud)

更新:目前,已解决:

 await lastValueFrom(createMyRecord()).catch((err) => {
            if (err instanceof EmptyError) {
                log.info(OK");
            }
        });
Run Code Online (Sandbox Code Playgroud)

但有更好的解决方案吗?

Jam*_*ore 8

lastValueFrom现在将配置参数作为其第二个参数,并且您可以指定一个默认值,如果可观察对象为空,则将发出该默认值:

await rxjs.lastValueFrom(observableThing, {defaultValue: "oh no - empty!"})
Run Code Online (Sandbox Code Playgroud)


Mrk*_*Sef 2

有更好的解决方案吗?

是和不是。

在您的情况下mergeMap(_ => EMPTY),将确保您的可观察对象完成而不发出值。承诺会解析为一个值,否则就会出错。因此,这里唯一要做的符合规范的事情就是抛出错误。

解决方法

你可以通过发出一些东西来回避这个问题。例如,我在null源完成后发出:

createMyRecord(): Observable<myRecord> {
  return of(TEMPLATE_DB).pipe(
    mergeMap((template) => doTask(template)),
    mergeMap(() => EMPTY),
    s => concat(s, of(null as myRecord))
  );
}
Run Code Online (Sandbox Code Playgroud)

null现在,一旦可观察对象成功完成,您的承诺就会得到解决。

一些惯用的东西

您可以更改调用方式,而不是更改代码。这样您就无需担心如何Observables交互Promises

而不是await lastValueFrom(createMyRecord());写:

createMyRecord().subscribe();
Run Code Online (Sandbox Code Playgroud)