Angular管道中的承诺会破坏应用程序吗



我有一个提供翻译管道的小库。如果我使用Observables,一切都很好。相关代码在这里:

https://gitlab.com/tobias47n9e/angular-fluent/-/blob/master/projects/angular-fluent/src/lib/fluent.pipe.ts#L32

this.localizationChanges.subscribe(() => {
this.fluentService
.translationObservable(key, args, getLocale(args))
.subscribe(value => this.value = value);
});

我想切换到Promises,所以管道只在加载区域设置并找到翻译后才切换值。但是,如果我将代码更改为以下内容,应用程序甚至无法再加载(它编译得很好(。

this.localizationChanges.subscribe(() => {
this.fluentService
.translate(key, args, getLocale(args))
.then(value => this.value = value);
});

这是Angular中不允许的吗?为什么它会编译,然后显示一个空页面,甚至没有打印错误消息?

首先,您可以使用RXJS或promise来实现这一点,但无论哪种方式,都有意为异步编程腾出空间,所以当您的transform方法在最后同步返回this.value时,我认为您没有达到预期效果?我猜它正在编译但你认为它不起作用的原因是它在起作用,但在你使用它之前没有计算出正确的值

为了保持在可观测值中,它应该返回一个可观测值。

transform(key: string, args?: any): Observable<string | null> {
if (!this.localizationChanges) {
this.localizationChanges = this.fluentService.localizationChanges;
}
return this.localizationChanges.pipe(
switchMap(() => this.fluentService
.translationObservable(key, args, getLocale(args))
)
);
}

然后在你的模板中,将| async链接到它的末尾。async管道将负责订阅、取消订阅、告诉组件在每次可观察到的源发出或更改时刷新,等等。

switchMap使得fluentService.translationObservable的任何仍在等待的结果在每次localizationChanges发射时被丢弃,用新的呼叫代替。

如果您只想发出一个值,那么promise就是一种选择。在这种情况下,你可能想要

async transform(key: string, args?: any): Promise<string | null> {
if (!this.localizationChanges) {
this.localizationChanges = this.fluentService.localizationChanges;
}
return this.localizationChanges.toPromise().then(
() => this.fluentService.translate(
key, args, getLocale(args)
)
);
}

然后在模板中,将| async链接到它的末尾,而不是重新创建那段代码。

如果我很好地理解这个问题,那么您的代码就有一个基本问题如果我使用Observables";是一个非常特殊的案例的结果。

让我们看看这个非常精简的版本的代码

function translationObservable(key) {
return of("Obs translates key: " + key);
}
function transform(key: string, args?: any): string | null {
let retValue: string;
const localizationChanges: BehaviorSubject<null> = new BehaviorSubject<null>(
null
);
localizationChanges.subscribe(() => {
translationObservable(key).subscribe((value) => (retValue = value));
});
return retValue;
}
console.log(transform("abc"));  // prints "Obs translates key: abc"

如果你运行这个代码,你最终会在控制台上打印出一条消息。

这段代码之所以有效,有一个原因,那就是我们正在同步使用Observables。换句话说,代码是逐行执行的,因此分配retValue = value出现在返回retValue之前。

但是承诺本质上是异步的。因此,传递给then方法的任何逻辑都将异步执行,即在Javascript引擎的另一个后续循环中执行。

这意味着,如果我们在上面的例子中使用Promise而不是Observable,我们将不会得到任何打印的消息

function translationPromise(key) {
return Promise.resolve("Promise translates key: " + key);
}
let retValue: string;
function transform(key: string, args?: any): string | null {
const localizationChanges: BehaviorSubject<null> = new BehaviorSubject<null>(
null
);
localizationChanges.subscribe(() => {
translationPromise(key).subscribe((value) => (retValue = value));
});
return retValue;
}
console.log(transform("abc"));  // prints undefined
// some time later it prints the value returned using Promises
setTimeout(() => {
console.log(retValue); 
}, 100);

总结一下,您的代码可能只有在使用of运算符创建Observable时才有效(由于不涉及异步操作,因此它可以同步工作(,但我怀疑它在必须调用异步功能(如获取区域设置文件(时是否有效。

如果你想构建一个异步工作的Angular管道,你需要遵循@JSmart523的答案

如前所述,在您的代码中,您正在订阅订阅中的Observable。这被认为与Observables不一致。

相关内容

  • 没有找到相关文章

最新更新