2

I am trying to save file array to spring boot server. One file is being saved at a time. i am iterating the file array with for loop and making a request for each file to be saved. Here i want next call to be made only after getting response for first file. I have tried the code given bellow but i am not able to achieve it.

Component.ts

public uploadNewsFiles() {

for (let index = 0; index < this.files.length; index++) {
  debugger;
  var body = new FormData();
 // alert(this.files[index].name);
  body.append('file', this.files[index]);
  this.uploading.push(true);
  this.uload(body,this.newsId,this.getFileDescriptionFormGroup(index)
  .controls['des'].value,index).then((status:any)=>
  {
    if (status.status === 'success') {
    //  alert('success');
      body.delete('file');
      this.uploading[index] = false;
      this.uploadingStatus.push(true);
     
    } else {
      body.delete('file');
      this.uploading[index] = false;
      this.uploadingStatus.push(false);
    }
  },(err)=>alert('failed'))
  }

   // body.append('newsId',this.newsId);
   }

  async uload(body,newsId,desc,index) {
  return await this.service.saveFiles(body, newsId,desc).toPromise();
  }

service.ts

public saveFiles(body,newsId,des) {

return this.http.post(this.url + '/saveFiles? 
newsId='+newsId+'&fileDescription='+des,body);
}
Community
  • 1
  • 1
omkar
  • 55
  • 1
  • 6

2 Answers2

0

you can use async await.

async uploadNewsFiles() {

for (let index = 0; index < this.files.length; index++) {
  var body = new FormData();
  body.append('file', this.files[index]);
  this.uploading.push(true);
  await this.uload(body,this.newsId,this.getFileDescriptionFormGroup(index)
  .controls['des'].value,index).then((status:any)=>
  {
     if (status.status === 'success') {
       body.delete('file');
       this.uploading[index] = false;
       this.uploadingStatus.push(true);
// here we are calling the 
     } else {
       body.delete('file');
       this.uploading[index] = false;
       this.uploadingStatus.push(false);
     }
    },(err)=>alert('failed'))
  }
}

uload(body,newsId,desc,index) {
  return new Promise((resolve, reject) => {
     this.service.saveFiles(body, newsId,desc).toPromise().then(resp => {
        resolve(resp); // here we are resolving our promise
     });
  });
}

Service

public saveFiles(body,newsId,des) {
 return this.http.post(this.url + '/saveFiles? 
         newsId='+newsId+'&fileDescription='+des,body);
}

I hope it helps you out.

Yash Rami
  • 2,276
  • 1
  • 10
  • 16
  • if you are using await you shouldn't use .then() it will already return the response. – hunterTR Jun 04 '19 at 13:21
  • But in this case we have api call so after consuming the api we resolve that promise isn’t it correct way? Should we write resolve with out writing a ‘then()’? – Yash Rami Jun 04 '19 at 14:05
0

Since you are using Angular we can take advantage of the rxjs library and instead of using toPromise and chain the observables from the http call, something like:

function modUploadFiles() {
  this.files
    .map((file, index) => {
      const body = new FormData();
      body.append("file", file);

      const newsId = this.newsId;

      const desc = this.getFileDescriptionFormGroup(index).controls["des"]
        .value;

      return this.service.saveFiles(body, newsId, desc).finally(status => {
        body.delete("file");
        this.uploading[index] = false;
        this.uploadingStatus.push(status.status === "success");
      })
    })
    .reduce((acc, next) => acc.flatMap(() => next))
    .subscribe(result => {/*Do something*/});
}

You can see more information in the following question:

Chaining Observables in RxJS

J. Pichardo
  • 3,077
  • 21
  • 37