Typescript Observables http.post和http.get处理问题

时间:2018-10-23 00:48:49

标签: javascript angular typescript rxjs

我正在一个项目中,我正在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运行直到输出返回?

3 个答案:

答案 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进行了更多阅读/研究之后,我能够使我的代码正常工作,我想感谢你们的反馈并将我的代码发布在下面。

在我的服务中,我创建了两个可观察对象:

  1. 第一个是获取队列服务器返回的jobId: // API: GET / FUNCTION /:jobID public getModelSummaryQueueId(modelSummaryParameters: ModelSummaryParameters): Observable<JobId>{ return this.http.post( $ {SERVER_URL}开始, modelSummaryParameters).map( (jobId) => jobId.json() ) }
  2. 使用第一段中的jobId来获取数据: // API: GET / FUNCTION /:results public listenModelSummary(jobId: JobId): Observable <ModelSummary>{ return this.http.get( $ {SERVER_URL}结果/ + jobId).map( (res) => res.json() ) }
  3. 下面是与上述2个服务一起使用的组件:

`

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');
});

});

`