【问题标题】:Multiple http calls with data transformation using angular 5使用 Angular 5 进行数据转换的多个 http 调用
【发布时间】:2018-08-06 10:43:34
【问题描述】:

我在我的 Angular 5 应用程序中进行了几个类似的 http 调用。我还需要应用类似的数据转换逻辑并将结果添加到数组中以显示在页面上。

第二次调用不是强制性的,是有条件的。

在 http 订阅上,正在进行数据转换并将其推送到数组。我尝试做数组 concat 来添加第二次调用的结果,但在页面上没有得到任何结果。

解决这个问题的最佳方法是什么?

if(oneReq) {
     this.http.get(url).subscribe ((message:       any[]) => {
     results.push({});
     }
   return results;

} else {
    forkJoin([this.http.get(url),        this.http.get(url)]) . subscribe ((message:    any[]) => {
     results.push({});
 }
  return results;
  }

【问题讨论】:

  • 分享一些示例代码。您使用的是旧的Http,还是新的HttpClient?您使用的是promises 还是observables.... 目前我们不知道。投反对票。
  • 我正在使用新的 httpclientmodule
  • 你使用什么变化检测策略?

标签: typescript http angular5 rxjs5


【解决方案1】:

使用

  • forkJoin 进行所有调用并等待完成(相当于Promise.all
  • defaultIfEmpty 用于第二次条件调用
  • map 和扩展运算符连接这些值
  • map再次改造这些iteam

    Observable
        .forkJoin(this.first$, this.second$.defaultIfEmpty([]))
        .map(([current, added]) => [...current, ...added])
        .map(item => transform(item))
        .subscribe(array=>{
           //do something with array
        });
    

【讨论】:

  • 纯代码帖子往往会被标记为低质量并被删除。您能否对此添加一些评论,以便其他人可以理解这是如何解决问题的?
【解决方案2】:

根据提供的代码,我可以看到几点:

  1. Observables 是异步的
  2. 条件块后可以订阅

异步

http.get 返回的 observable 不会立即发出。它首先等待 http 响应,然后执行subscribe 中的代码。它也不会阻止执行。因此,在等待响应时,它会继续运行return results。当响应最终到来时,subscribe 块运行。

这是一个例子。我在这里模拟了 Angular 的 http.get,因为将 Angular 包含到 sn-p 中并不是那么简单:

// Angular's `http.get` returns an RxJS Observable
// which `emits` and `completes` when the http response comes through
// So this simulates the `get` 
// using an Observable which emits and completes after 500 milliseconds
const http = { get: () =>  Rx.Observable.of('messages').delay(500) }

const results = []
const url = ''

function getMessages() {
  http.get(url).subscribe(messages => {
    // this block is run after 500ms
    results.push({});
    console.log('C: ', results) // [{}]
  })
  return results; // this code does not wait 500ms, it runs immediately
}

const returned = getMessages()
console.log('A: ', returned) // []
console.log('B: ', results)  // []

// logs will show:
// A: []
// B: []
// C: [{}]
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.min.js"></script>

条件块后订阅

const forkJoin = Rx.Observable.forkJoin

// Let's pretend our endpoint just response to `get` with the url as its "messages"
const http = {
  get(url) {
    return Rx.Observable.of([url]).delay(500)
  }
}

const url1 = 'one.com', url2 = 'two.com', url3 = 'three.com'

let results = []
let oneReq

function getMessages() {
  let response;
  if (oneReq) {
    response =  http.get(url1) // emits [one.com]
  } else {
    response = forkJoin([
      http.get(url2), http.get(url3)
    ]) //emits [[two.com], [three.com]]
  }
  
  // we return the Observable
  return response.do(handleMessages)
}

function handleMessages(messages) {
  // because of the forkJoin,
  // you need to check for the nested array
  // [[two.com], [one.com]]
  // that forkJoin makes before you concat
  results = results.concat(messages)
}

oneReq = true
getMessages().subscribe(messages => {
  console.log(results)
})

oneReq = false
getMessages().subscribe(messages => {
  console.log(results)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.min.js"></script>

请注意,Observable 是从 getMessages() 返回的。

要重新迭代异步方面,从getMessages() 返回results 不会产生您可能期望的结果,因为subscribe() 中的代码稍后执行。

Angular 组件可以为您检测更改,因此如果您不喜欢订阅 getMessages(),则在组件内有两个选择:

选项 1:

// change the `do` to subscribe
function getMessages(): void {
  // if/else...
  response.subscribe(handleMessage)
}

请注意,您现在无法返回 messages。返回 response.subscribe(handleMessage) 将返回 Subscription,而不是 Observable。 Take a look at this about subscriptions

选项 2:

在模板中使用async 管道:

<ul>
  <li *ngFor="let result of results | async">{{result}}</li>
<ul>

这是关于异步管道的 documentationarticle

【讨论】:

  • 那么第二个请求取决于第一个响应的响应?
  • 不,他们是独立的
  • 看看你写的一些代码不起作用真的很有帮助。
  • 但是在我下班之前我忍不住又一次尝试了答案:P 更新了答案以显示两个流之外的条件
  • 目前,我正在使用一个 if 条件 - forkjoin 2 个调用/订阅,而在 else 中只使用 http/subscribe。由于某种原因,我无法使用函数来格式化响应 - 我不得不复制逻辑。
猜你喜欢
  • 1970-01-01
  • 2018-10-18
  • 2020-07-03
  • 1970-01-01
  • 2018-09-01
  • 1970-01-01
  • 2018-11-12
  • 1970-01-01
  • 2017-11-27
相关资源
最近更新 更多