gpt4 book ai didi

javascript - 顺序调用HTTP请求并处理订阅中的加载动画

转载 作者:行者123 更新时间:2023-12-03 03:10:36 27 4
gpt4 key购买 nike

我正在开发一个 Angular 4.4.4 应用程序,其中商家可以向客户赠送积分;为此,我进行了 httpclient srevice 调用(为此,我使用 cancateMap 虽然不知道该使用什么)。

我有多个商家,所有商家都可以向用户提供积分,因此我想为每个商家依次调用 httpClient req(一个接一个)。作为响应,我想在添加积分时显示 View 增加中的积分,例如计数器和加载栏。例如**

if starbucks add 20 points then in response view should show points incrementing till 20 and determinant loader will be shown till it completes 100%. I want to show this for each and every request

对于装载机,我使用 Material 决定因素装载机**:下面是我的组件代码

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { SharedService } from '../services/shared.service';
import { CommonService } from '../services/common.service';
import { Observable } from 'rxjs/Rx';
@Component({
selector: 'app-dashboard',
templateUrl: './onboarding.component.html',
styleUrls: ['./onboarding.component.scss']
})
export class DashboardComponent implements OnInit {
public merchantsList: Object[];
public points: number = 0;
public counter: number = 0;
public merchantName: string;
public percentage: number;
constructor(private router: Router, private commonService: CommonService, private sharedService: SharedService) { }

ngOnInit() {
this.merchantsList = this.sharedService.getMerchants();
this.transferPoints();

}

transferPoints() {
let data = {
"points": 20,
"issueToPartyName": "O=User1,L=New York,C=US",
"issuerBankPartyRef": "1"
};

Observable.of(...this.merchantsList)
.concatMap((merchant: Object) => {
return this.commonService.getAllMerchatPoints(merchant, data).map((res) => {
return res
});
}).subscribe((res) => {

let timer = Observable.interval(200).subscribe(() => {
this.merchantName = res.initiator;
this.points++;
this.counter++;
this.percentage = (this.counter / 20) * 100;
if (this.percentage === 100) {
timer.unsubscribe();
this.percentage = 0;
this.counter = 0;
}
});
});
}
}

transferPoints() 是我调用的方法,用于使用 concateMap 进行连续的 http 调用,然后在其订阅中我得到转移的积分和商家名称:

HTML 是:

<div class="mobile-img">
<div class="home-card flex-container flex-col-direction flex-center-center">
<div>
<img class="icon" src="assets/images/user-big.png" />
</div>
<div>
<div class="amount">{{points}}</div>
<div class="subtext">Points</div>
</div>

<div class="state">Fetching your reward points...</div>

<div class="vendor">{{merchantName|| 'Uber'}}</div>

<mat-progress-bar mode="determinate" value="{{percentage}}"></mat-progress-bar>
</div>
</div>

服务代码是:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHandler, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { LoaderService } from './loader.service';
interface NodeResponse {
name: string;
nodeName: string;
nodeType: string;
port: number;
initiator?:string;
}


@Injectable()
export class CommonService extends HttpClient {
private contextPath = "url";
constructor(private http: HttpClient, public httpHandler: HttpHandler, public loaderService: LoaderService) {

}
getAllNodes(): Observable<NodeResponse[]> {
return this.http.get<NodeResponse[]>(`${this.contextPath}:10007/api/transferpoints/getAllNodesInfo`);
}

getAllMerchatPoints(merchant, data): Observable<NodeResponse> {
return this.http.put<NodeResponse>(`${this.contextPath}:${merchant.port}/api/transferpoints/issueandtransfer`, data);
}
}

getAllMerchatPoints 是我正在调用的服务

问题是我无法按顺序从每个请求中获取数据。我的意思是,当与星巴克相关的http请求完成时,我想增加点并显示加载的点,就像它的获取点一样;完成星巴克请求后,优步请求应该触发并进一步想要增加点并显示已加载,就像它的获取点一样。

我在订阅中尝试过以下操作;使用间隔是因为我想显示加载程序移动到最后;但是它无法正常工作。

    let timer = Observable.interval(200).subscribe(() => {
this.merchantName = res.initiator;
this.points++;
this.counter++;
this.percentage = (this.counter / 20) * 100;
if (this.percentage === 100) {
timer.unsubscribe();
this.percentage = 0;
this.counter = 0;
}
});

我使用的运算符正确吗?连接映射?有没有其他方法可以实现上述目标?

最佳答案

映射运算符

在应用中使用 concatMapflatMap 取决于您是否想保留商家的排序。
请记住,http 是异步的,因此某些调用的响应速度可能比其他调用快。 concatMap 保持原始顺序,而 flatMap 在响应到达后立即发出。

否则,它们都执行相同的工作 - 展开内部可观察量。

计时器

虽然从技术上讲计时器代码没有任何问题,但我认为它使图片变得困惑。基本上,http 响应不会顺利到达,因此除非您知道响应时间总是少于 200 毫秒,否则您不能期望此计时器以 200 毫秒的间隔发出。

Observable.of(...this.merchantsList).concatMap(

的结果

not able to get data from each request sequentially

您解释了您想要得到什么,但没有解释您正在得到什么。我不明白为什么你不能得到连续的结果,特别是使用 concatMap

尝试注释掉计时器代码并放入 console.log(res) 以查看得到的响应顺序。

.. so two intervals are running concurrently as they are async !.. wondering is there any way to run interval also sequentially

所以,我认为这个 block 在外部订阅内

let timer = Observable.interval(200).subscribe(() => {
...
}

运行速度快并返回到下一个商家响应。内部订阅是独立运行的(正如你所说的异步)。如果没有间隔包装器,内部部分将同步运行,并且一切都会按顺序进行。但我猜你想要一点延迟以获得正确的屏幕效果。

也许你需要订阅外部的间隔而不是内部的间隔,就像这样

}).delay(200).subscribe((res) => { 

使用combineLatest()

这就是我迄今为止所掌握的这种方法。

const merchantPoints$ = Observable.of(...this.merchantsList)
.concatMap((merchant: Object) => {
return this.commonService.getAllMerchatPoints(merchant, data).map((res) => {
return res
});
});
const timer$ = Observable.interval(200);
Observable.combineLatest(merchantPoints$, timer$)
.subscribe(combined => {
const res = combined[0];
this.merchantName = res.initiator;
this.points++;
this.counter++;
this.percentage = (this.counter / 20) * 100;
if (this.percentage === 100) {
// timer.unsubscribe();
this.percentage = 0;
this.counter = 0;
}
});

关于javascript - 顺序调用HTTP请求并处理订阅中的加载动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46968732/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com