2016-11-14 30 views
0

我需要很多連鎖http請求,請求的數量是可變的,他們不依賴與前一個結果,我只需要保持的返回的對象最後的要求。不能與angular2 HTTP中使用concatMap()

我一直在,第一個解決方案使用Observable.concat()作品給這個thread兩種解決方案,而是一個貢獻者建議我執行一個更優雅的方式,通過使用concatMap()

這裏是我當前的代碼:

MyComponent的

submitForms() { 
    var formToSubmit = [...]; // Contains dirty forms that be sent to the backend (they are simple Angular2 Components) 
    var id = '123'; 

    Rx.Observable.from(formToSubmit) 
      .concatMap(
        (form) => { 
         return this.formPartService.submitFormPart(id, form.getContext(), form.getValues()); 
        } 
      ) 
       .combineAll() 
       .subscribe((val) => { 
        console.log(val); // Should return an array of each value returned. I'll keep the last one. 
       }); 
} 

正如你所看到的,我有需要提交到後臺的所有髒形式的數組。我從這個數組中創建一個Observable,然後使用concatMap()來訂閱傳遞函數的Observable並等待結果,然後觸發下一個訂閱。

下面是從我FormPartService

submitFormPart(id: string, part: string, data: any) { 

    let body = JSON.stringify({ 
     id: id, 
     part: part, 
     data: data 
    }); 

    return this.http.post('/form-part', body) 
        .map((res) => { 
          let body = res.json(); 
          if (body.data){ 
           return body.data; 
          } 
         } 
        ); 
} 

submitFormPart()方法應該簡單地返回一個簡單的冷觀察到。一切都應該很好地工作......

當我提交我的形式,我有錯誤unknown type returned,完整的堆棧跟蹤:

core.umd.js?e2a5:3462 EXCEPTION: unknown type returnedErrorHandler.handleError @ core.umd.js?e2a5:3462next @ core.umd.js?e2a5:6924schedulerFn @ core.umd.js?e2a5:6172SafeSubscriber.__tryOrUnsub @ VM1077851:223SafeSubscriber.next @ VM1077851:172Subscriber._next @ VM1077851:125Subscriber.next @ VM1077851:89Subject.next @ VM1077847:55EventEmitter.emit @ core.umd.js?e2a5:6164onError @ core.umd.js?e2a5:6388onHandleError @ core.umd.js?e2a5:6263ZoneDelegate.handleError @ zone.js?fad3:207Zone.runTask @ zone.js?fad3:139ZoneTask.invoke @ zone.js?fad3:304 
core.umd.js?e2a5:3467 ORIGINAL STACKTRACE:ErrorHandler.handleError @ core.umd.js?e2a5:3467next @ core.umd.js?e2a5:6924schedulerFn @ core.umd.js?e2a5:6172SafeSubscriber.__tryOrUnsub @ VM1077851:223SafeSubscriber.next @ VM1077851:172Subscriber._next @ VM1077851:125Subscriber.next @ VM1077851:89Subject.next @ VM1077847:55EventEmitter.emit @ core.umd.js?e2a5:6164onError @ core.umd.js?e2a5:6388onHandleError @ core.umd.js?e2a5:6263ZoneDelegate.handleError @ zone.js?fad3:207Zone.runTask @ zone.js?fad3:139ZoneTask.invoke @ zone.js?fad3:304 
core.umd.js?e2a5:3468 TypeError: unknown type returned 
    at Object.subscribeToResult (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:297:2), <anonymous>:69:27) 
    at CombineLatestSubscriber._complete (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:797:2), <anonymous>:108:46) 
    at CombineLatestSubscriber.Subscriber.complete (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:131:2), <anonymous>:114:18) 
    at MergeMapSubscriber.notifyComplete (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:430:2), <anonymous>:155:30) 
    at InnerSubscriber._complete (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:315:2), <anonymous>:30:21) 
    at InnerSubscriber.Subscriber.complete (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:131:2), <anonymous>:114:18) 
    at MapSubscriber.Subscriber._complete (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:131:2), <anonymous>:132:26) 
    at MapSubscriber.Subscriber.complete (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:131:2), <anonymous>:114:18) 
    at XMLHttpRequest.onLoad (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:261:2), <anonymous>:1499:42) 
    at ZoneDelegate.invokeTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:236:37) 
    at Object.onInvokeTask (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:101:2), <anonymous>:6233:41) 
    at ZoneDelegate.invokeTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:235:42) 
    at Zone.runTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:136:47) 
    at XMLHttpRequest.ZoneTask.invoke (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:304:33) 
    ------------- Elapsed: 336 ms; At: Mon Nov 14 2016 13:58:04 GMT+0100 (Paris, Madrid) ------------- 
    at Object.onScheduleTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2666:2), <anonymous>:76:18) 
    at ZoneDelegate.scheduleTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:213:49) 
    at Zone.scheduleEventTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:156:39) 
    at zoneAwareAddListener (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:773:14) 
    at XMLHttpRequest.addEventListener (eval at createNamedFn (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2)), <anonymous>:3:43) 
    at Observable.eval [as _subscribe] (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:261:2), <anonymous>:1540:22) 
    at Observable.subscribe (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:113:2), <anonymous>:56:27) 
    at Observable._subscribe (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:113:2), <anonymous>:114:28) 
    at MapOperator.call (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:273:2), <anonymous>:54:23) 
    at Observable.subscribe (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:113:2), <anonymous>:53:22) 
    at Object.subscribeToResult (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:297:2), <anonymous>:21:27) 
    at MergeMapSubscriber._innerSub (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:430:2), <anonymous>:120:38) 
    at MergeMapSubscriber._tryNext (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:430:2), <anonymous>:117:14) 
    at MergeMapSubscriber._next (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:430:2), <anonymous>:100:18) 
    at MergeMapSubscriber.notifyComplete (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:430:2), <anonymous>:152:18) 
    at InnerSubscriber._complete (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:315:2), <anonymous>:30:21) 
    at InnerSubscriber.Subscriber.complete (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:131:2), <anonymous>:114:18) 
    at MapSubscriber.Subscriber._complete (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:131:2), <anonymous>:132:26) 
    at MapSubscriber.Subscriber.complete (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:131:2), <anonymous>:114:18) 
    at XMLHttpRequest.onLoad (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:261:2), <anonymous>:1499:42) 
    at ZoneDelegate.invokeTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:236:37) 
    at Object.onInvokeTask (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:101:2), <anonymous>:6233:41) 
    at ZoneDelegate.invokeTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:235:42) 
    at Zone.runTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:136:47) 
    at XMLHttpRequest.ZoneTask.invoke (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:304:33) 
    ------------- Elapsed: 861 ms; At: Mon Nov 14 2016 13:58:03 GMT+0100 (Paris, Madrid) ------------- 
    at Object.onScheduleTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2666:2), <anonymous>:76:18) 
    at ZoneDelegate.scheduleTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:213:49) 
    at Zone.scheduleEventTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:156:39) 
    at zoneAwareAddListener (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:773:14) 
    at XMLHttpRequest.addEventListener (eval at createNamedFn (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2)), <anonymous>:3:43) 
    at Observable.eval [as _subscribe] (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:261:2), <anonymous>:1540:22) 
    at Observable.subscribe (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:113:2), <anonymous>:56:27) 
    at Observable._subscribe (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:113:2), <anonymous>:114:28) 
    at MapOperator.call (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:273:2), <anonymous>:54:23) 
    at Observable.subscribe (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:113:2), <anonymous>:53:22) 
    at Object.subscribeToResult (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:297:2), <anonymous>:21:27) 
    at MergeMapSubscriber._innerSub (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:430:2), <anonymous>:120:38) 
    at MergeMapSubscriber._tryNext (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:430:2), <anonymous>:117:14) 
    at MergeMapSubscriber._next (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:430:2), <anonymous>:100:18) 
    at MergeMapSubscriber.Subscriber.next (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:131:2), <anonymous>:89:18) 
    at ArrayObservable._subscribe (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:370:2), <anonymous>:114:28) 
    at ArrayObservable.Observable.subscribe (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:113:2), <anonymous>:56:27) 
    at Observable._subscribe (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:113:2), <anonymous>:114:28) 
    at MergeMapOperator.call (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:430:2), <anonymous>:75:23) 
    at Observable.subscribe (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:113:2), <anonymous>:53:22) 
    at Observable._subscribe (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:113:2), <anonymous>:114:28) 
    at CombineLatestOperator.call (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:797:2), <anonymous>:74:23) 
    at Observable.subscribe (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:113:2), <anonymous>:53:22) 
    at EditorComponent.submitAll (eval at <anonymous> (http://192.168.33.10:7777/app.js:1220:2), <anonymous>:81:18) 
    at _View_EditorComponent0._handle_click_52_0 (EditorComponent.ngfactory.js:602:28) 
    at eval (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:101:2), <anonymous>:9698:28) 
    at eval (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:209:2), <anonymous>:1877:40) 
    at eval (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:209:2), <anonymous>:1990:115) 
    at ZoneDelegate.invoke (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:203:28) 
    at Object.onInvoke (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:101:2), <anonymous>:6242:41) 
    at ZoneDelegate.invoke (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:202:34) 
    at Zone.runGuarded (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:110:47) 
    at NgZoneImpl.runInnerGuarded (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:101:2), <anonymous>:6271:82) 
    at NgZone.runGuarded (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:101:2), <anonymous>:6504:77) 
    at HTMLButtonElement.outsideHandler (eval at <anonymous> (http://192.168.33.10:7777/vendor.js:209:2), <anonymous>:1990:83) 
    at ZoneDelegate.invokeTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:236:37) 
    at Zone.runTask (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:136:47) 
    at HTMLButtonElement.ZoneTask.invoke (eval at <anonymous> (http://192.168.33.10:7777/polyfills.js:2660:2), <anonymous>:304:33)ErrorHandler.handleError @ core.umd.js?e2a5:3468next @ core.umd.js?e2a5:6924schedulerFn @ core.umd.js?e2a5:6172SafeSubscriber.__tryOrUnsub @ VM1077851:223SafeSubscriber.next @ VM1077851:172Subscriber._next @ VM1077851:125Subscriber.next @ VM1077851:89Subject.next @ VM1077847:55EventEmitter.emit @ core.umd.js?e2a5:6164onError @ core.umd.js?e2a5:6388onHandleError @ core.umd.js?e2a5:6263ZoneDelegate.handleError @ zone.js?fad3:207Zone.runTask @ zone.js?fad3:139ZoneTask.invoke @ zone.js?fad3:304 
VM1077851:227 Uncaught TypeError: unknown type returned(…) 

我找不到在哪裏這個錯誤的來源。 我嘗試以下,從我已經提供的原始示例測試,並以一定的方式來調試:

MyComponent的

submitForms() { 
    ... 
    Rx.Observable.from(formToSubmit) 
       .concatMap(
        (form) => { 
         return Rx.Observable.of(this.formPartService.submitFormPart(id, form.getPartName(), form.getValues()); 
        } 
... 
} 

返回可觀察到的可觀察到的一樣...這個錯誤消失了,http調用很好地執行,但是它們並行地被同時執行。 這不是我想要的,這當然不可行,但它可能只是表明問題來自我的submitFormPart()的回報,因此從Angular2返回的Http.post().map()表示concatMap()不讚賞...

如果它是有用的,這裏是我的最新版本:

"@angular/common": "2.0.0", 
"@angular/compiler": "2.0.0", 
"@angular/core": "2.0.0", 
"@angular/forms": "2.0.0", 
"@angular/http": "2.0.0", 
"@angular/material": "^2.0.0-alpha.9-3", 
"@angular/platform-browser": "2.0.0", 
"@angular/platform-browser-dynamic": "2.0.0", 
"@angular/router": "3.0.0", 
"rxjs": "5.0.0-beta.12" 

我沒有嘗試尚未升級這些...

感謝您的幫助

+1

你能剝奪這只是必要的最低?我不知道錯誤在哪裏出現。也許這'Rx.Observable.from(formToSubmit)'?什麼是'formToSubmit'? – martin

+0

嗨,我盡了最大努力去除元素。 'formToSubmit'是一個簡單的數組,包含指向封裝角度表單的子組件的'@ ViewChild'變量。就像我上面所說的,我使用這個數組是因爲提交表單的數量是可變的,並且取決於它們是否髒。我從這個數組創建一個Observable來逐個處理這些表單,就像貢獻者建議我做的那樣 – DlafCreative

回答

0

我只需要保留最後一次請求的返回對象。

使用.takeLast(n)以獲得最新的N觀察到的,對於你的情況,請嘗試更改您的代碼以

Rx.Observable.from(formToSubmit) 
    .concatMap(
     (form) => { 
      return this.formPartService.submitFormPart(id, form.getContext(), form.getValues()); 
     } 
    ) 
    .takeLast(1) // get only the latest observable 
    .subscribe((val) => { 
     console.log(val); // Now this should return the last emitted value 
    }); 

Plunker

0

你可以做到以下幾點:

Rx.Observable.zip(
    formToSubmit.map(form => this.formPartService.submitFormPart(id, form.getContext(), form.getValues())) 
).subscribe(results => { 
    let firstFormResult = results[0]; 
    let secondFormResult = result[1]; 
    ... etc. etc. 
}); 

我這樣做,無論我有多個獨立請求......只要所有請求完成, Observable.zip將調用您的訂閱。