我正在一个项目中,我正在Angular(打字稿)/ Node中构建一个简单的前端,以调用后端服务器来执行不同的任务。这些任务需要花费时间才能执行,因此需要在后端服务器上排队。我按照以下教程解决了这个问题:https://github.com/realpython/flask-by-example,一切似乎都正常。
现在我要结束前端的工作,其中大多数代码已经使用Angular和Rxjs用Typescript编写了。我正在尝试在Typescript中复制以下代码:
https://github.com/dimoreira/word-frequency/blob/master/static/main.js
此代码包含两个函数,其中第一个函数“ getModelSummary”(示例中的getResults)通过以下方式调用post方法:
public getModelSummary(modelSummaryParameters: ModelSummaryParameters): Observable<ModelSummary> {
return this.http.post(`${SERVER_URL}start`, modelSummaryParameters)
.map(res => res.json())
;
}
将作业放入队列中,并为后端服务器上的该功能分配一个jobID。第二个函数“ listenModelSummary”,最好在第一个函数之后以jobId作为输入执行,并在很短的间隔内循环检查作业是否已完成:
public listenModelSummary(jobID: string) {
return this.http.get(`${SERVER_URL}results/` + jobID).map(
(res) => res.json()
);
}
工作完成后,它需要返回结果,这将更新前端。
我是Typescript,Observables和rxjs的新手,并想寻求正确的方法。我不想使用javascript,但想在我的前端代码堆栈中尽可能坚持使用Typescript。我该如何使用第一个函数通过输出“ jobID”来调用第二个函数,并让第二个函数通过interval运行直到输出返回?
答案 0 :(得分:0)
可观察的对象很棒,而且是Angular的HttpClient类返回的对象的类型,但是在我看来,有时候,处理它们比使用promise复杂得多。
是的,将Observable转换为Promise的额外操作对性能有轻微的影响,但是您会获得一个更简单的编程模型。
如果需要等待第一个函数完成,然后将返回的值交给另一个函数,则可以执行以下操作:
async getModelSummary(modelSummaryParameters: ModelSummaryParameters): Promise<ModelSummary> {
return this.http.post(`${SERVER_URL}start`, modelSummaryParameters).toPromise();
}
async doStuff(): Promise<void> {
const modelSummary = await this.get(modelSummary(params);
// not sure if you need to assign this to your viewmodel,
// what's returned, etc
this.listenModelSummary(modelSummary)
}
如果您对使用Observables有点犹豫,我建议您使用concatMap模式,该模式将如下所示:
doStuff(modelSummaryParameters: ModelSummaryParameters): Observable<ModelSummary> {
return this.http
.post(`${SERVER_URL}start`, modelSummaryParameters)
.pipe(
concatMap(modelSummary => <Observable<ModelSummary>> this.listenModelSummary(modelSummary))
);
}
这是一篇有关Observables的不同映射解决方案的文章:https://blog.angularindepth.com/practical-rxjs-in-the-wild-requests-with-concatmap-vs-mergemap-vs-forkjoin-11e5b2efe293可能会帮助您。
答案 1 :(得分:0)
您可以尝试以下操作:
getModelSummary(modelSummaryParameters: ModelSummaryParameters): Promise<ModelSummary> {
return this.http.post(`${SERVER_URL}start`, modelSummaryParameters).toPromise();
}
async someMethodInYourComponent() {
const modelSummary = await this.get(modelSummary(params);
this.listenModelSummary(modelSummary)
}
// OR
someMethodInYourComponent() {
this.get(modelSummary(params).then(() => {
this.listenModelSummary(modelSummary);
});
}
答案 2 :(得分:0)
在对rxjs进行了更多阅读/研究之后,我能够使我的代码正常工作,我想感谢你们的反馈并将我的代码发布在下面。
在我的服务中,我创建了两个可观察对象:
// API: GET / FUNCTION /:jobID
public getModelSummaryQueueId(modelSummaryParameters: ModelSummaryParameters): Observable<JobId>{
return this.http.post(
$ {SERVER_URL}开始, modelSummaryParameters).map(
(jobId) => jobId.json()
)
}
// API: GET / FUNCTION /:results
public listenModelSummary(jobId: JobId): Observable <ModelSummary>{
return this.http.get(
$ {SERVER_URL}结果/ + jobId).map(
(res) => res.json()
)
}
`
this.subscription = this.developmentService.getModelSummaryQueueId(this.modelSummaryParameters)
.subscribe((jobId) => {
return this.developmentService.listenModelSummary(jobId)
// use switchMap to pull value from observable and check if it completes
.switchMap((modelSummary) =>
// if value has not changed then invoke observable again else return
modelSummary.toString() === 'Nay!'
? Observable.throw(console.log('...Processing Request...'))
// ? Observable.throw(this.modelSummary = modelSummary)
: Observable.of(modelSummary)
)
.retryWhen((attempts) => {
return Observable
// specify number of attempts
.range(1,20)
.zip(attempts, function(i) {
return(i);
})
.flatMap((res:any) => {
// res is a counter of how many attempts
console.log("number of attempts: ", res);
res = 'heartbeat - ' + res
this.getProgressBar(res);
// this.res = res;
// delay request
return Observable.of(res).delay(100)
})
})
// .subscribe(this.displayData);
// .subscribe(modelSummary => console.log(modelSummary));
.subscribe((modelSummary) => {
console.log("FINAL RESULT: ", modelSummary)
this.modelSummary = modelSummary;
this.getProgressBar('Done');
});
});
`