如何使程序等到在Angular中执行可观察到的
我正在从事一个角度项目,我的情况是,使用可观察到的产品来打电话给后端。
这是代码的样子。
getProducts () : Product[] {
this.http.get<[]>(this.m_baseURL+'/products').subscribe(res => {
console.log(res)
this.products = res;
});
return this.products
}
问题是,返回语句不会等待上述语句被执行。在我的组件中,我得到一个空数组。我在服务和组件中使用控制台日志检查了。事实证明,在可观察到的值之前,将执行返回语句。
我该如何停止直到完成工作,就像异步等待一样。我应该使用普通异步而不是可观察的吗?
这是我的第一个角度项目,所以如果问题是新手,请原谅我。
I'm working on an angular project, I have a situation where making a call to backend using an observable to fetch products.
Here is how the code looks like.
getProducts () : Product[] {
this.http.get<[]>(this.m_baseURL+'/products').subscribe(res => {
console.log(res)
this.products = res;
});
return this.products
}
Problem is, the return statement doesn't wait for the above statement to get executed. And in my component, I get an empty array. I checked using console log in both service and component. And it turns out return statement gets executed before observable is done assigning the value.
How do I make it stop until it completes its job, just like async await does. Should I use normal async await instead of observable?
This is my first Angular project, so please pardon me if the question is novice.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
而不是等待返回时间,某些任务使用反应性方法。
someService.ts
someComponents.ts
someComponent.html
许多方法可以解决这个常见问题。也有许多改善它的方法。这是一种方式。我不知道您的过滤是如何工作的,但是如果可能的话,我希望使用
|异步
管道完全避免手动订阅,并用额外的管道过滤或过滤可观察到的本身。Instead of waiting for returns to time some tasks use reactive approach.
SomeService.ts
SomeComponents.ts
SomeComponent.html
Many ways to approach this common problem. Many ways to improve it as well. This is one way. I don't know how your filtering works, but if possible I would prefer to use
| async
pipe to avoid manual subscribing at all and filter with an additional pipe or filter the observable itself.要等待可观察到的第一个值,您可以使用
firstValueFrom()
。此方法很危险,因为它可能会导致您的应用程序无限期地悬挂,始终包含超时机制。一个更好的设计是只提出HTTP请求以更新
this.products
,并且只需使用它的变量,就像它始终具有内容一样,您可以在订阅中做其他事情,如果您希望副作用到发生在更新中。当收到HTTP响应时,更改检测将自动更新您的HTML,但是您始终可以使用
更改eTectorRef.detectChanges()
强制强制。上述HTML将为空白,直到您的第一个订阅完成为止,此时应该自动更新。
如果您正在使用服务,则看起来这样:
服务
组件
两个包装器方法就是这样,因此您不必编写
服务
在您的HTML中。如果您希望在不同的组件中发生唯一的副作用,则将
this.products
转换为主题,然后您可以在products
更改时订阅并执行回调。capysubject
允许您将值初始化为空数组。Service
如果要将主体的值保存在组件中,而不是使用
async
管道订阅,请确保在销毁组件时取消订阅。那是因为此主题无法像httpclient
的可观察到的那样完成,因此除非取消订阅,否则订阅将保留在内存中。组件
To wait for the first value from an observable you can use
firstValueFrom()
. This method is dangerous since it can cause your application to hang indefinitely, always include a timeout mechanism.A better design is to instead only make the http request to update
this.products
, and just use the variable like it always has content, you can do some other things in your subscription if you want side effects to happen on update.Change detection will automatically update your html when an http response is received, but you can always force it with
ChangeDetectorRef.detectChanges()
.The above html will be blank until your first subscription completes, at which point it should automatically update.
If you're using a service it would look like this:
service
component
The two wrapper methods are just so you don't have to write
service
in your html.If you want unique side effects to happen in different components, you would convert
this.products
to a subject, and then you can subscribe and execute a callback wheneverproducts
changes. ABehaviorSubject
lets you initialize the value to an empty array.service
If you want to save the value of the subject in the component rather than subscribing with the
async
pipe, make sure to unsubscribe when the component is destroyed. That's because this subject does not complete like the observables fromHttpClient
, so subscriptions will remain in memory unless unsubscribed.component
您可以对此使用异步 /等待模式,但我建议您反对。了解如何使用可观察物进行异步编程。
加载产品的服务方法应返回可观察的可观察:
消费代码应订阅可观察到的数据并获取数据:
You could use an async / await pattern for this, but I recommend against it. Learn how to program asyncronously using Observables.
The service method to load products should return the Observable:
The consuming code should subscribe to the Observable and get the data:
在这里做事的角度方法是不要返回
product []
,而是要返回可观察到的本身:然后,您使用
async
管道来订阅此观察力,并且Angular将自动显示数据。这就是这是一种服务方法的情况。如果您在组件中进行此操作,那么简单的答案是:不要。将其放在服务中。那就是他们的目的。
强烈建议您尝试Angular的《英雄之旅》教程。他们讨论了这种事情。
The Angular way of doing things here is to not return a
Product[]
, but to return the Observable itself:You then use the
async
pipe to subscribe to this Observable, and Angular will automatically display the data.That's for the case where this is a service method. If you're doing this in a component, the simple answer is: don't. Put this in a service. That's what they're for.
Strongly suggest you try Angular's Tour of Heroes tutorial. They go over this sort of thing.
Angular不支持同步可观测值或HTTPCLCCLIENT调用
坏消息! Angular不支持任何类型的真正同步调用!
此混淆了想要等待数据检索数据的新角开发人员,但是没有办法延迟
可观察的
键入角度,因为它的构建围绕等待 - 方便技术。httpclient
,Promise
或fetch
都等待等待 等待等待,也是如此。使A 真正同步请求的唯一方法是使用旧的
XMLHTTPREQUEST()
同步呼叫数据,该数据仍然可以在Angular中使用。但这在像Angular这样的异步技术中不是一个不错的选择。请继续阅读...
许多角度程序员对此感到困惑的是,是否可以将可观察物被欺骗到表演同步(由异步 - 瓦特承诺等)。但是他们不能。许多开发人员认为添加或删除计时器,延迟或回调功能会改变其基本异步行为,但事实并非如此。 a 同步进程是指停止或 blocks 的整个外部代码继续运行直到过程完成的过程(如传统的JavaScript)。
可观察到
,httpclient
和promises
都是 asynchronous 对象。异步代码在其自己的时间轴上运行,这意味着在触发异步代码后,JavaScript跳到可观察到的或异步代码后的下一个代码块代码并保持运行。你不能停止。一旦可观察到的数据返回数据,脚本就会跳回可观察到的处理以完成其处理,然后返回到之前关闭的位置。
除了使用真正的老式调用
xmlhttprequest()
之外,您的最佳策略是将可观察到的可观察到的ngoninit(),ngoninit(),),组件的构造函数或路由护罩,并在其数据处理管道结束时添加回调方法,该方法跳到您的同步代码。这样可以保证您的代码才能运行,直到可观察到的数据处理可观察到。然后迫使Angular可观察
暂停并收集所有数据并在调用代码的下一部分之前完成其事件。这将模拟使用可观察到的同步代码事件。以下是一个例子。伪造Angular中的同步呼叫,
您可以通过在可观察到的订阅区域中使用简单的回调函数来伪造同步调用。在可观察后,下面的角组件中的自定义功能同步运行。
dosomethingNew()
方法将在httpclient
(AN 可观察到 type)之后才能运行。 )订阅完成其数据收集,并将其分配给 products 属性:Angular Does Not Support Synchronous Observables or HttpClient Calls
BAD NEWS!! Angular does not support any type of true synchronous calls!
This confuses new Angular developers who want to wait for data to be retrieved in Angular, but there is no way to delay an
Observable
type in Angular as its build around await-async technology. The same goes forHttpClient
,Promise
, orFetch
which are all await-async type constructs.The only way to make a truly synchronous request is using the old
XMLHttpRequest()
synchronous call for data, which still can be used in Angular. But that is not a good choice in an asynchronous technology like Angular.Read on...
What many Angular programmers get confused about is whether Observables can be tricked into acting synchronous (wrapped by async-await promises, etc). But they cannot. Many developers think adding or removing timers, delays, or callback functions changes their basic asynchronous behavior, but they do not. A Synchronous process means a thread or a call to a process that stops or blocks all outside code from continuing to run until the process is complete (like traditional JavaScript).
Observables
,HttpClient
, andPromises
are all asynchronous objects.Asynchronous code runs in its own timeline, which means after the async code is triggered, JavaScript jumps down to the next code block code AFTER the Observable or async code and keeps running. You cannot stop that. Once the Observable returns with its data, the script jumps back to the Observable to complete its processing, then returns to where it left off before.
Other than using a truly old-fashioned call to
XMLHttpRequest()
, your best strategy is to wrap the Observable into a deadend angular method like a custom function, ngOnInit(), the component's constructor, or a routing guard and add on a callback method at the end of its data processing pipeline that jumps to your synchronous code. That guarantees your code does not run until the data processing Observable is done. That then forces theAngular Observable
to pause and gather all its data and complete its events before calling the next part of your code. And this simulates a synchronous code event using Observables. Below is an example of that.Fake a Synchronous Call in Angular
You can fake a synchronous call by using a simple callback function in the subscription area of your Observable. The custom function in the Angular Component below runs synchronously after the Observable.The
doSomethingNew()
method will not run until theHttpClient
(an Observable type) subscription completes its gathering of data and assigns it to the products property: