在Angular 4

时间:2017-11-13 23:49:11

标签: angular for-loop asynchronous response

所以我试图用for循环快速连续创建包。我尝试使用for循环和api调用来执行此操作,此api调用会生成包。我的循环必须等待每次通话的返回,但它没有。

我也不想将我的backend.service改为Promise而不是Observable。是否可以使用Observable执行此操作?

component.ts

for (let i = 0; i < this.dataArray.length; i++) {
  this.backend.createPackage(this.package, this.hasPackagePhoto, this.wantsPackageLabel).subscribe(data => {
    let d = data as any;
    this.backend.packageTrackTrace = d.package.tracktrace;
    this.backend.awsLink = d.label;
  }, error => {
    this.backend.showMessage(false, 'Foutcode 2a: Het toevoegen van een pakket is niet gelukt.');
    console.log(error);
    this.errorMsg = "Verkeerde postcode!";
  }
  );
}

backend.service.ts

createPackage(p: Package, photo: Boolean, label: Boolean): Observable<Response> {
    const h = new Headers({ 'Content-Type': 'application/json', 'x-access-token': this.auth.getToken() });
    const options = new RequestOptions({ headers: h });

    const pt: any = {
        type: p.type,
        sender: p.sender,
        recipient: p.recipient,
        weight: p.weight,
        value: p.value,
        photo: photo,
        label: label,
        instructions: p.instructions
    };
    if (p.owner != null) {
        pt.owner = p.owner;
    }
    if (p.size != null) {
        pt.size = p.size;
    }

    return this.http.post(`${this.config.apiBase}/packages`, pt, options)
        .map((res:Response) => {
            this.newPackageCallbacks.forEach(cb => {
                cb();
            });
            return this.parseJSON(res);
        })
        .catch(this.handleError);
}

2 个答案:

答案 0 :(得分:0)

我会为它创建一个递归函数:

createPackages(count: number, i = 0) {
  if (i >= count) return;
  this.backend.createPackage(this.package, this.hasPackagePhoto, this.wantsPackageLabel).subscribe(data => {
    let d = data as any;
    this.backend.packageTrackTrace = d.package.tracktrace;
    this.backend.awsLink = d.label;
    this.createPackages(count, ++i);
  }, error => {
    this.backend.showMessage(false, 'Foutcode 2a: Het toevoegen van een pakket is niet gelukt.');
    console.log(error);
    this.errorMsg = "Verkeerde postcode!";
  });
}

并调用:this.createPackages(this.dataArray.length);

答案 1 :(得分:0)

您可以使循环成为可观察对象,并使concatMap()成为createPackage。

如果回调很慢,回调可能会有问题。您可能希望在外部订阅中执行这些。

Observable.from(this.dataArray)
  .concatMap(() => 
    this.backend.createPackage(this.package, this.hasPackagePhoto, this.wantsPackageLabel);
  )
  .subscribe(
    data => {

      // Execute callbacks here if they need to complete before next package 
      this.backend.newPackageCallbacks.forEach(cb => {
        cb();
      });

      let d = data as any;
      this.backend.packageTrackTrace = d.package.tracktrace;
      this.backend.awsLink = d.label;
    }, 
    error => {
      this.backend.showMessage(false, 'Foutcode 2a: Het toevoegen van een pakket is niet gelukt.');
      console.log(error);
      this.errorMsg = "Verkeerde postcode!";
    }
   )

为了说明concatMap()flatMap(),这里有一些虚拟代码

&#13;
&#13;
console.clear() 
const Observable = Rx.Observable;

// Dummy setup for testing
let counter = 0;
const backendService = {
  createThePackage: () => {
    return Observable.of('y' + counter++)
      .delay((6 - counter) * 10) // delay to resolve in order of 3, 2, 1
  }
}
const dataArray = [1,2,3]


// flatMap takes order of resolving
counter = 0;
Observable.from(dataArray)
  .flatMap(() => { 
    return backendService.createThePackage();
  })
  .subscribe(x => {
    console.log('flatMap: ' + x)
  })

// concatMap takes order of creating
counter = 0;
Observable.from(dataArray)
  .concatMap(() => { 
    return backendService.createThePackage();
  })
  .subscribe(x => {
    console.log('concatMap: ' + x)
  })
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.js"></script>
&#13;
&#13;
&#13;