我可以调用observable中的API以特定的顺序吗?

huangapple go评论79阅读模式
英文:

can I call the apis in observable in a certain sequence/order

问题

我正在学习angular中的Observable主题。我尝试在Observable内部调用API,并希望它们按照我指定的顺序运行。

下面是我的组件类代码:

  1. import { HttpClient } from '@angular/common/http';
  2. import { Component, OnDestroy, OnInit } from '@angular/core';
  3. import { Observable } from 'rxjs';
  4. @Component({
  5. selector: 'app-flav4',
  6. templateUrl: './flav4.component.html',
  7. styleUrls: ['./flav4.component.css']
  8. })
  9. export class Flav4Component implements OnInit, OnDestroy {
  10. orderStatus!: any;
  11. data!: Observable<any>;
  12. constructor(private httpcli: HttpClient) { }
  13. ngOnInit(): void {
  14. this.data = new Observable(observer => {
  15. this.httpcli.get("http://localhost:9898/api/orderStart", { headers: { "content-type": "application/json" } }).subscribe(data => {
  16. console.warn(data);
  17. this.orderStatus = data;
  18. observer.next(this.orderStatus);
  19. });
  20. this.httpcli.get("http://localhost:9898/api/orderWait", { headers: { "content-type": "application/json" } }).subscribe(data => {
  21. console.warn(data);
  22. this.orderStatus = data;
  23. observer.next(this.orderStatus);
  24. });
  25. this.httpcli.get("http://localhost:9898/api/orderComplete", { headers: { "content-type": "application/json" } }).subscribe(data => {
  26. console.warn(data);
  27. this orderStatus = data;
  28. observer.next(this.orderStatus);
  29. });
  30. });
  31. this.data.subscribe(val => this.orderStatus = val);
  32. }
  33. ngOnDestroy(): void {
  34. }
  35. }

我期望控制台输出为:

  1. {"status": "orderStarted"}
  2. {"status": "orderWaiting"}
  3. {"status": "orderCompleted"}

然而,我得到了以下输出:

  1. {"status": "orderStarted"}
  2. {"status": "orderCompleted"}
  3. {"status": "orderWaiting"}

为了获得所期望的输出,即按照特定的顺序或序列运行API,你应该做以下更改:

你可以使用concatMap 操作符来确保API按照你的顺序运行。例如:

  1. import { concatMap, switchMap } from 'rxjs/operators';
  2. // ...
  3. this.data = new Observable(observer => {
  4. this.httpcli.get("http://localhost:9898/api/orderStart", { headers: { "content-type": "application/json" } }).pipe(
  5. concatMap(data => {
  6. console.warn(data);
  7. this.orderStatus = data;
  8. observer.next(this.orderStatus);
  9. return this.httpcli.get("http://localhost:9898/api/orderWait", { headers: { "content-type": "application/json" });
  10. }),
  11. concatMap(data => {
  12. console.warn(data);
  13. this.orderStatus = data;
  14. observer.next(this.orderStatus);
  15. return this.httpcli.get("http://localhost:9898/api/orderComplete", { headers: { "content-type": "application/json" });
  16. })
  17. ).subscribe(data => {
  18. console.warn(data);
  19. this.orderStatus = data;
  20. observer.next(this.orderStatus);
  21. });
  22. });
  23. // ...

这样,你可以确保API按照你的指定顺序运行。

英文:

I am learning angular Observable topic. I was trying to call apis inside Observable and hoping that they will run in an order in which I have stated them.

Below is my component class code:

  1. import { HttpClient } from &#39;@angular/common/http&#39;;
  2. import { Component, OnDestroy, OnInit } from &#39;@angular/core&#39;;
  3. import { Observable } from &#39;rxjs&#39;;
  4. @Component({
  5. selector: &#39;app-flav4&#39;,
  6. templateUrl: &#39;./flav4.component.html&#39;,
  7. styleUrls: [&#39;./flav4.component.css&#39;]
  8. })
  9. export class Flav4Component implements OnInit, OnDestroy {
  10. orderStatus!: any;
  11. data!: Observable&lt;any&gt;;
  12. constructor(private httpcli: HttpClient) { }
  13. ngOnInit(): void {
  14. this.data = new Observable(observer =&gt; {
  15. this.httpcli.get(&quot;http://localhost:9898/api/orderStart&quot;, { headers: { &quot;content-type&quot;: &quot;application/json&quot; } }).subscribe(data =&gt; {
  16. console.warn(data);
  17. this.orderStatus = data;
  18. observer.next(this.orderStatus);
  19. });
  20. this.httpcli.get(&quot;http://localhost:9898/api/orderWait&quot;, { headers: { &quot;content-type&quot;: &quot;application/json&quot; } }).subscribe(data =&gt; {
  21. console.warn(data);
  22. this.orderStatus = data;
  23. observer.next(this.orderStatus);
  24. });
  25. this.httpcli.get(&quot;http://localhost:9898/api/orderComplete&quot;, { headers: { &quot;content-type&quot;: &quot;application/json&quot; } }).subscribe(data =&gt; {
  26. console.warn(data);
  27. this.orderStatus = data;
  28. observer.next(this.orderStatus);
  29. });
  30. });
  31. this.data.subscribe(val =&gt; this.orderStatus = val);
  32. }
  33. ngOnDestroy(): void {
  34. }
  35. }

I was expecting console output to be

  1. {&quot;status&quot;: &quot;orderStarted&quot;}
  2. {&quot;status&quot;: &quot;orderWaiting&quot;}
  3. {&quot;status&quot;: &quot;orderCompleted&quot;}

However I got below output

  1. {&quot;status&quot;: &quot;orderStarted&quot;}
  2. {&quot;status&quot;: &quot;orderCompleted&quot;}
  3. {&quot;status&quot;: &quot;orderWaiting&quot;}

What should I change in this code in order to get desired output i.e to run APIs in a certain order or sequence.

答案1

得分: 1

这是正常行为,因为HTTP请求是异步的。

您可以尝试使用mergeMap,也被称为RxJS库中的flatmap,来链接它们。我建议您也查看一下行为。

参考以下示例:

  1. import { HttpClient } from '@angular/common/http';
  2. import { Component, OnDestroy, OnInit } from '@angular/core';
  3. import { Observable } from 'rxjs';
  4. import { mergeMap } from 'rxjs/operators';
  5. @Component({
  6. selector: 'app-flav4',
  7. templateUrl: './flav4.component.html',
  8. styleUrls: ['./flav4.component.css']
  9. })
  10. export class Flav4Component implements OnInit, OnDestroy {
  11. orderStatus!: any;
  12. data!: Observable<any>;
  13. constructor(private httpcli: HttpClient) { }
  14. ngOnInit(): void {
  15. this.data = this.httpcli.get("http://localhost:9898/api/orderStart", { headers: { "content-type": "application/json" } }).pipe(
  16. mergeMap(orderStart => {
  17. console.warn(orderStart);
  18. this.orderStatus = orderStart;
  19. return this.httpcli.get("http://localhost:9898/api/orderWait", { headers: { "content-type": "application/json" } });
  20. }),
  21. mergeMap(orderWait => {
  22. console.warn(orderWait);
  23. this.orderStatus = orderWait;
  24. return this.httpcli.get("http://localhost:9898/api/orderComplete", { headers: { "content-type": "application/json" } });
  25. })
  26. );
  27. this.data.subscribe(orderComplete => {
  28. console.warn(orderComplete);
  29. this.orderStatus = orderComplete;
  30. });
  31. }
  32. ngOnDestroy(): void {
  33. }
  34. }

这是您提供的代码的中文翻译。

英文:

This is normal behaviour as HTTP requests are asynchronous.

You can try chaining them with mergeMap also known as flatmap from RxJS library. I suggest you take a look at the behaviours as well.

Something like this as reference

  1. import { HttpClient } from &#39;@angular/common/http&#39;;
  2. import { Component, OnDestroy, OnInit } from &#39;@angular/core&#39;;
  3. import { Observable } from &#39;rxjs&#39;;
  4. import { mergeMap } from &#39;rxjs/operators&#39;;
  5. @Component({
  6. selector: &#39;app-flav4&#39;,
  7. templateUrl: &#39;./flav4.component.html&#39;,
  8. styleUrls: [&#39;./flav4.component.css&#39;]
  9. })
  10. export class Flav4Component implements OnInit, OnDestroy {
  11. orderStatus!: any;
  12. data!: Observable&lt;any&gt;;
  13. constructor(private httpcli: HttpClient) { }
  14. ngOnInit(): void {
  15. this.data = this.httpcli.get(&quot;http://localhost:9898/api/orderStart&quot;, { headers: { &quot;content-type&quot;: &quot;application/json&quot; } }).pipe(
  16. mergeMap(orderStart =&gt; {
  17. console.warn(orderStart);
  18. this.orderStatus = orderStart;
  19. return this.httpcli.get(&quot;http://localhost:9898/api/orderWait&quot;, { headers: { &quot;content-type&quot;: &quot;application/json&quot; } });
  20. }),
  21. mergeMap(orderWait =&gt; {
  22. console.warn(orderWait);
  23. this.orderStatus = orderWait;
  24. return this.httpcli.get(&quot;http://localhost:9898/api/orderComplete&quot;, { headers: { &quot;content-type&quot;: &quot;application/json&quot; } });
  25. })
  26. );
  27. this.data.subscribe(orderComplete =&gt; {
  28. console.warn(orderComplete);
  29. this.orderStatus = orderComplete;
  30. });
  31. }
  32. ngOnDestroy(): void {
  33. }
  34. }

huangapple
  • 本文由 发表于 2023年2月18日 02:05:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/75487834.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定