For Loop returning a promise

I have a for loop where several values often have different size, and if the 2nd one is smaller than the first one, it rushes through the for loop and triggers an event which moves to the next page and doesn’t allow the slower file to upload. I need a for loop with a promise so that it’d wait for all the files to load. Any ideas how to implement if?

Does Promise.all() look like it would be of assistance?

How do I use with with a for loop?

  for(let i=0; i<array.length; i++) {

  }

That’s impossible to answer without knowing what array is made of. Can you share some actual semi-working code? That will make this all go a lot smoother.

Sure! Thanks a lot!!

  this.phoneStorage.SQLStorageGet("UID").then((value) => {
    this.UID = value;
    this.listingID = (10492964271759)-(+ new Date().getTime());
    for(let i=0; i<this.photosArray.length; i++) {
      this.firebaseStorage.accessFile(this.file.tempDirectory, this.photoFileName[i]).then((result) => {
        this.firebaseStorage.uploadFile(this.photoFileName[i], result, this.UID, this.listingID, "picture", null).then(() => {
          this.firebaseStorage.getFile(this.photoFileName[i], this.UID, this.listingID).then((downloadURL) => {
            this.phoneStorage.SQLStorageSet("photo"+i, downloadURL).then((result) => {
               if(i === (this.photosArray.length -1)) { //<=1's overtakes 0's and end the process before 0's makes it
                this.phoneStorage.writeToFirebaseDB(this.UID, this.listingID).then((value, key, index) => {
                  this.loading.dismiss().then(() => {
                    this.navCtrl.push(CompletePage).catch((error: any) => console.log('Push error: ', error));
                  });
                });
                }
            });
          });
        });
      });
   }
  }).catch((error: any) => console.log('SQLStorageGet UID error: ', error));

First up, I find the notion of parallel arrays error-prone and unwieldy, so I’m going to pretend that instead of photoFileName, each element of photosArray has a name and id property. You can either do it this way or sort of adapt the basic structure below.

Although all this could be inlined, it’s probably clearer to build up the array separately:

let loading = this._loadings.create();
loading.present();

let actions = this.photosArray.map((photo) => {
  return this.firebaseStorage.uploadFile(photo.name, result, this.UID, this.listingID, "picture", null)
    .then(() => this.firebaseStorage.getFile(photo.name, this.UID, this.listingID))
    .then((downloadURL) => this.phoneStorage.SQLStorageSet(photo.id, downloadURL));
});

Promise.all(actions)
  .then(() => this.phoneStorage.writeToFirebaseDB(this.UID, this.listingID))
  .then(() => loading.dismiss())
  .then(() => this.navCtrl.push(CompletePage));

Note that I made the loading indicator lexically scoped. Storing them in object properties is a bad idea because it encourages accidentally reusing them or double-disposing them.

2 Likes

Thanks so much! I’ve implemented exactly as you have recommended, and it works like a charm!!

can you help me here?