本文介绍了无法将concatMap()与angular2 Http一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要链接许多http请求,请求的数量是可变的,并且它们与上一个请求的结果无关,我只需要保留最后一个请求的返回对象.

I need to chain many http requests, the number of request is variable and they are not dependant from the result of the previous one, I just need to keep the returned object of the last request.

在此线程上,我得到了两种解决方案,使用 Observable.concat()的第一个解决方案是可行的,但是一位贡献者建议我使用 concatMap()来执行此操作的更优雅的方式.

I've been given two solutions on this thread, the first solution using Observable.concat() works, but a contributor suggested me a more elegant way to perform that, by using 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并等待结果,然后触发下一个订阅.

As you can see, I have an array with all dirty forms that need to be submitted to the backend. I create an Observable from this array, then I use concatMap() to subscribe to the Observable of the passed function and wait for the result, before firing the next subscription.

这是我的 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;
                            }
                        }
                    );
}

它应该简单地返回一个简单的Cold Observable.一切都应该正常工作...

It should simply return a simple cold Observable. Everything should work fine...

提交表单时,出现错误返回未知类型,完整的stacktrace:

When I submit my forms, I have the error unknown type returned, the complete stacktrace :

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(…)

我找不到此错误的来源.我尝试了以下操作,以从提供的原始示例中进行测试,并以某种方式进行调试:

I can't find where this error comes from.I tried the following, to test from the raw example I've been provided, and to debug in a certain way :

MyComponent

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

返回一个Observable的Observable ...这样,错误消失了,http调用得到了很好的执行,但是它们同时并行执行.那不是我想要的,当然当然也不可行,但这可能只是表明问题出在我的 submitFormPart()的返回上,因此是 Http.post的返回上().map()来自Angular2的 concatMap()不满意...

Returning an Observable of an Observable... like this, the error disappear, the http calls are well executed, but they are executed at the same time in parallel.That's not what I want, and that's certainly not viable of course, but it may just show that the problem comes from the return of my submitFormPart(), and so the return of Http.post().map() from Angular2 that concatMap() doesn't appreciate...

如果有用的话,这是我当前的版本:

If it can be useful, here are my current versions :

"@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"

我还没有尝试升级这些东西...

I didn't try to upgrade these yet...

感谢您的帮助

推荐答案

您可以执行以下操作:

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将调用您的订阅.

I do this whereever I have multiple independent requests... as soon as ALL requests are completed, Observable.zip will invoke your subscription.

这篇关于无法将concatMap()与angular2 Http一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 18:22