2017-05-26 53 views
3

在我的服務類中,我正在循環一個http get請求,並使用rxjs forkJoin將所有響應組合到一個observable中,並將其返回給我的組件。對於每個返回的響應,我需要向json添加兩個屬性(readySystem是一個對象,serviceType是一個字符串)。每個循環的迭代值都是不同的。角度循環HTTP請求映射值到響應

我該如何保存/存儲/保留和and/map值並將它們添加到正確的響應中?

以我試圖在下面做的方式,兩者的值在最終可觀察值中返回的每個響應中都是相同的。

getServices() { 

    for (var x = 0; x < this.service.items.length; x++){ 
     var num = Object.keys(this.service.items[x].links).length; 

     for (var key in this.service.items[x].links) { 
      var systemName = this.service.items[x].systemName; 
      var environment = this.service.items[x].environment; 
      var server = this.service.items[x].server; 
      var port = this.service.items[x].port; 
      var linkName = this.service.items[x].links[key]; 
      var serviceType = key; 
      this.observables.push(
      this.http.get('http://localhost:3000/myapi/get/service?server=' + server + '&service=' + linkName) 
      .map((res:Response) => { 
       var output = res.json() 
       for (var obj in output) { 
        if (output.hasOwnProperty(obj)){ 

         var readySystem = new System(systemName, 
         environment, 
         server, 
         port, 
         linkName); 

        output[obj].System = readySystem; 
        output[obj].serviceType = serviceType; 
        } 
       } 
       return output; 
     }) 
      ); 
     } 
     }; 
     return Observable.forkJoin(this.observables); 
}; 

更新:隨着下面的答案提供建議的代碼更改,我得到的輸出,如:

0: Array(33) 
1: System 
    systemName: "my system" 
    environment: "my environment" 
    etc. 
2: "myservice" 
3: Array(35) 
4: System 
    etc. 
5: "myotherservice" 

但是,我們需要的是:

0: Array(33) 
0: Object 
    > System 
     systemName: "my system" 
     environment: "my environment" 
     etc. 
    serviceType: "myservice" 
1: Object 
    > System 
     systemName: "my system" 
     environment: "my environment" 
     etc. 
    serviceType: "myotherservice" 
etc. 
1: Array(35) 
0: Object 

回答

0

只需添加這些值使用Observable.of

function getObsevrables(observables, readySystem, serviceType) { 
    return Rx.Observable.forkJoin([ 
    Rx.Observable.of(readySystem), 
    Rx.Observable.of(serviceType), 
    ...observables 
    ]); 
} 

getObsevrables([Rx.Observable.of(1), Rx.Observable.of(2)], 
      {ready: true}, 'type1') 
    .subscribe(x=>console.log(x)) 

UPDATE:

我嘗試更新你的代碼。

getServices() { 

for (var x = 0; x < this.service.items.length; x++) { 
    var num = Object.keys(this.service.items[x].links).length; 

    for (var key in this.service.items[x].links) { 
    var systemName = this.service.items[x].systemName; 
    var environment = this.service.items[x].environment; 
    var server = this.service.items[x].server; 
    var port = this.service.items[x].port; 
    var linkName = this.service.items[x].links[key]; 
    var serviceType = key; 

    var readySystem = new System(systemName, 
     environment, 
     server, 
     port, 
     linkName); 

    // getObservables([Observable.of(1), Observable.of(2)], readySystem, serviceType).subscribe(x => console.log(x)); 

    this.observables.push(
     Observable.combineLatest(
     this.http.get('http://localhost:3000/myapi/get/service?server=' + server + '&service=' + linkName) 
     .map((res: Response) => { 
      var output = res.json(); 
      return output; 
     }); 
     }, 
     Observable.of(serviceType), 
     Observable.of(readySystem) 
    ) 
    ); 
} 
} 
+0

謝謝。我明白這個函數在做什麼,但是{ready:true}的目的是什麼,我應該在什麼時候和從哪裏調用這個函數呢? – HendPro12

+0

在一個循環中,你創建了一個可觀察對象的數組,這個對象將執行http調用,正如我所理解的,你爲每個forkJoin - readySystem和serviceType創建了兩個變量。因此,您只需使用Observable.of將它們添加到可觀察數組中,並執行與現在一樣的返回。 –

+0

我的forkJoin發生在我的內部和外部循環外的return語句中。我相信我需要將內部循環中的兩個變量添加到每個單獨的observables中,然後將它們推入到我的observable數組中。 – HendPro12

0

這可能是一個簡單的經典的JS關閉問題。當所有異步調用(http.get S和Observable.forkJoin)都解決了,所有的功能範圍的var S(XNUM關鍵SYSTEMNAME環境服務器端口,...等等)在for循環內設置爲它們的最後一個值。最簡單的解決方案是使用ES6塊範圍letconst聲明。

因此,嘗試更改您的代碼是這樣的:

for (let x = 0; x < this.service.items.length; x++){ 
    let num = Object.keys(this.service.items[x].links).length; 

    for (let key in this.service.items[x].links) { 
    let systemName = this.service.items[x].systemName; 
    let environment = this.service.items[x].environment; 
    let server = this.service.items[x].server; 
    let port = this.service.items[x].port; 
    let linkName = this.service.items[x].links[key]; 
    let serviceType = key; 

    let url = `http://localhost:3000/myapi/get/service?server=${server}&service=${linkName}`; 
    this.observables.push(this.http.get(url) 
     .map((res:Response) => { 
     let output = res.json(); 
     for (let obj in output) { 
      if (output.hasOwnProperty(obj)) { 

      let readySystem = new System(systemName, 
       environment, 
       server, 
       port, 
       linkName 
      ); 

      output[obj].System = readySystem; 
      output[obj].serviceType = serviceType; 
      } 
     } 
     return output; 
     } 
    )); 
    }}; 
    return Observable.forkJoin(this.observables); 
}; 

,並在一般情況下,沒有理由不與角2/4編碼時使用​​。

你也可以使用Array.forEach()功能(我認爲this.service.items是因爲它的長度財產的數組)重寫你的第一for循環:

this.service.items.forEach(item => { 
    let num = Object.keys(item.links).length; 

    for (let key in item.links) { 
    let systemName = item.systemName; 
    let environment = item.environment; 
    let server = item.server; 
    let port = item.port; 
    let linkName = item.links[key]; 
    let serviceType = key; 

    let url = `http://localhost:3000/myapi/get/service?server=${server}&service=${linkName}`; 
    this.observables.push(this.http.get(url) 
     .map((res:Response) => { 
     let output = res.json(); 
     for (let obj in output) { 
      if (output.hasOwnProperty(obj)) { 

      let readySystem = new System(systemName, 
       environment, 
       server, 
       port, 
       linkName 
      ); 

      output[obj].System = readySystem; 
      output[obj].serviceType = serviceType; 
      } 
     } 
     return output; 
     } 
    )); 
    }}; 
    return Observable.forkJoin(this.observables); 
}); 
0

這是一個封閉的問題。根據您的原始代碼:

for (var key in this.service.items[x].links) { 
    var systemName = this.service.items[x].systemName; 

在這裏,你可能會認爲你正在創建執行塊的新systemName變量各一次。實際上,該變量只創建一次,每次執行該塊時只會分配新值。

this.observables.push(
      this.http.get('http://localhost:3000/myapi/get/service?server=' + server + '&service=' + linkName) 
      .map(res => { 
       var output = res.json() 
       for (var obj in output) { 
       if (output.hasOwnProperty(obj)){ 
        var readySystem = new System(systemName, 

這裏map內回調不會立即當systemName具有正確的值在循環中執行:因爲下面你異步調用http.get的區別是很重要的。它只是存儲在內存中以供稍後執行(當http.get返回結果時)。回調的存儲體不包含systemName值,只有對變量的引用。

現在,每次執行循環時,它都會爲systemName分配一個新值並存儲回調。循環結束時,systemName的值是循環分配的最後一個值。

過了一段時間,http.get請求開始完成,存儲的回調被執行,他們讀取systemName,他們都獲得相同的最後一個值。這是你正在經歷的。

最簡單的修復方法實際上是爲每個塊執行創建一個新的systemName變量。這可以通過使用let而不是var來實現。所以只需使用let所有相關變量將解決問題:

let systemName = this.service.items[x].systemName; 
let environment = this.service.items[x].environment; 
let server = this.service.items[x].server; 
let port = this.service.items[x].port; 
let linkName = this.service.items[x].links[key]; 
let serviceType = key;