Angular 2 : Chain http requests with concat()

标签 angular rxjs angular2-http angular2-observables

我在链接多个 HTTP 请求时遇到一些困难。

首先,在返回冷 Observable 的服务方法中定义请求。

FormPartService

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

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

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

我要提交的表单部分的数量可变,具体取决于它们是否脏,因此我迭代填充这些表单的数组。每个调用都不依赖于前一个调用的返回,我最终需要的只是最后一个调用之后返回的内容

为此,我尝试了 concat() 运算符,在我看来,它比 switchMap() 更适合我的情况。这是我的尝试:

组件

var formToSubmit = [...]; // Contains dirty forms that be sent to the backend
var id = '123';
var stream$; // Will contain the first Observable

formToSubmit.forEach((form, index) => {
    if (index === 0) {
        // Set stream$ with the first Observable
        stream$ = this.formPartService.submitFormPart(id, form.getPartName(), form.getValues())
    }
    else {
        // Concat the first Observable with the others
        let obs$ = this.formPartService.submitFormPart(id, form.getPartName(), form.getValues());
        stream$.concat( obs$ );
    }
});

stream$.subscribe((globalForm) => {
    console.log(globalForm);
})

不幸的是,它不起作用。当我一步步调试时,一切都很顺利,我用观察者设置了 stream$stream$.concat() 不会中断。但是我在网络中得到的只是只有第一个请求,而不是链接的请求。

我做错了什么? 非常感谢

编辑 我用 Kwintep 提供的示例替换了我的代码,以优化请求链。不幸的是,这些请求都被很好地一一执行,但是一旦完成,我就会收到以下错误 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(…)

最佳答案

您的代码可以优化为:

// Mocks an http call that takes 1 second to complete
function fakeRequest(id) {
  console.log('doing the request for id ' + id);
  return Rx.Observable.of(id).delay(1000);
}

let items = ["1", "2", "3"];

// create an observable from the array that emits every item one after one
Rx.Observable.from(items)
   // use concatMap, this operator accepts a function that returns an observable.
   // It will subscribe to this observable and not take on any next values
   // untill that observable completes.
   // So it will get '1' and perform the request. As soon as this one completes
   // it will handle the next value, which will be '2' and so on.
  .concatMap(
    (val) => {
      return fakeRequest(val)
   })
   // Use combine all to make sure the subscription below isn't call untill
   // every element in the original array is handled.
  .combineAll()
   // Get back an array with the results from every call, just take the last one
   // if you really need it
  .subscribe((val) => console.log(val));

内嵌评论。 Jsbin 示例如下:http://jsbin.com/hequvokaya/edit?js,console

关于 Angular 2 : Chain http requests with concat(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40533016/

相关文章:

html - 带有 Angular 组件的 Flexbox 布局

javascript - 如何通过 RxJS 限制对 React 组件方法的调用

forms - 类型 'http' 上不存在属性 'Component',Angular 2

javascript - 错误 [预处理] : Can not load "webpack"! (webpack@2.2.1; karma@1.4.1)

javascript - "Workspace needs to be loaded before it is used"on ng new

angular - 我应该在组件销毁时完成BehaviorSubject – Angular2

node.js - 类型 '{header:Header;}' 的参数不可分配给类型 'RequestOptionsArgs' 的参数

javascript - 配置 Angular 2 HTTP 服务

javascript - Angular 2 中针对每个请求的自定义 Http header

angular - 使用 Angular 和 ASP.NET Core 将 API 调用重定向到 Azure 上的根 URL