【发布时间】:2017-03-28 15:46:43
【问题描述】:
我需要链接许多http请求,请求的数量是可变的,它们不依赖于前一个的结果,我只需要保留最后一个请求的返回对象。
我得到了关于这个thread 的两个解决方案,第一个使用Observable.concat() 的解决方案有效,但一位贡献者建议我使用concatMap() 更优雅的方式来执行此操作。
这是我当前的代码:
我的组件
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() 方法
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;
}
}
);
}
它应该简单地返回一个简单的冷 Observable。一切都应该正常...
当我提交表单时,出现错误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(…)
我找不到这个错误的来源。 我尝试了以下方法,从我提供的原始示例中进行测试,并以某种方式进行调试:
我的组件
submitForms() {
...
Rx.Observable.from(formToSubmit)
.concatMap(
(form) => {
return Rx.Observable.of(this.formPartService.submitFormPart(id, form.getPartName(), form.getValues());
}
...
}
Returning an Observable of an Observable...这样,错误消失,http调用执行良好,但同时并行执行。
这不是我想要的,当然这当然不可行,但它可能只是表明问题来自我的submitFormPart() 的返回,因此Http.post().map() 从 Angular2 的返回 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"
我还没有尝试升级这些...
感谢您的帮助
【问题讨论】:
-
你能把它只剥离到必要的最低限度吗?我不知道抛出的错误在哪里。也许这个
Rx.Observable.from(formToSubmit)?formToSubmit是什么? -
嗨,我已尽力将元素剥离到最低限度。
formToSubmit是一个简单的数组,包含指向封装角形式的子组件的@ViewChild变量。就像我上面说的,我使用这个数组是因为要提交的表单数量是可变的,并且取决于它们是否脏。我从这个数组创建了一个 Observable 来逐个处理这些表单,就像贡献者建议我做的那样
标签: angular rxjs angular2-http angular2-observables