How to convert this data into a JSON Object to send through API?

I have been trying to solve this issue for some hours already and I can´t wrap my mind about what I should really do guys:

Basically I have the following code where first I get some data (first urls and then urls.location), and then I´ll try to send this arrayphotos array as an object through an API patch request.

uploadPhoto(e){
       
        let arrayphotos = [{}]
        new Promise(function() {
            
            for(let i= 0; i<e.target.files.length; i++){
                ReactS3.uploadFile(e.target.files[i], s3configUpload)
                .then((urls) => {
                    
                    arrayphotos.push((urls.location))
                })
                .catch((err) => {alert(err)})
            }
            console.log(arrayphotos)
          }).then(
            
            axios.patch(`${apiGatewayDevStage}/add-pictures`, {
                site: this.props.match.params.gallery_name + "_" + this.state.authenticatedUser,
                photos: arrayphotos
            }).then(() => {
                console.log('DB-Galleries en Dynamo updated')
            }).catch(err => console.log(err))
           
          )
        
    }

I think where the problem is that the function is sending three objects (three photos ulrs) instead of sending in one object the three urls. When I console log after the arrayphotos is completed, this is what it appears:

photofreeCode

So basically I guess that because the array is completed with three objects, then the DB just gets an empty array (I guess because of an error, because it doesnt appear any error in the axios error handler tbh).

How can I make the for loop so the array has only ONE object and inside the urls?

Hello!

I think the problem lies with how you’re uploading the files.

When you execute this:

for(let i= 0; i<e.target.files.length; i++){
                ReactS3.uploadFile(e.target.files[i], s3configUpload)
                .then((urls) => {
                    
                    arrayphotos.push((urls.location))
                })
                .catch((err) => {alert(err)})
            }

You’re basically iterating and uploading each file without waiting for the response. The problem with this is that the for loop doesn’t wait and executes the next step until it finishes, while the file may or may not have been uploaded.

Did you check the console to see the output? Does console.log(arrayphotos) show anything?

On the other hand, is the axios.patch even executing? I don’t think so :stuck_out_tongue:, because for the next then to execute on a chained promise, the previous step must return a promise, which is not the case :sweat_smile:.

Look at this example and see the console (press F12 or Control + Shift + i and click on the Console tab). Pay extra attention to the order of the console messages. This will become a problem when your uploads get bigger (in size, I mean) and you will not even notice it (a silent bug).

A solution I have used in the past is using recursion. The idea is to call a function that uploads the first file and then calls itself, uploading each file until there are no more files to upload.

Hint

Since we’re here to learn, you may want to build your own solution, but I’ll leave an implementation that I’ve used in the past to give you an idea (it’s not tested so be careful)

function myUpload(files, config, done, result = [], index = 0) {
  // When the index is equal or greater to the length of the files array
  if (index >= files.length) {
    // call the done function, which should trigger the next step
    return done(result);
  }
  const currentFile = files[index];
  S3.uploadFile(currentFile, config).then((url) => {
    result.push({ status: "ok", error: null, file: url.location });
    myUpload(files, config, done, result, index++);
  }).catch(e) => {
    result.push({ status: "failed", error: e, file });
    myUpload(files, config, result, index++);
  });
}

// On the main function
function main() {
  return new Promise(() => {
    myUpload(e.target.files, s3config, (uploadResult) => {
      // Now you can pass the upload result to axios patch.
    });
  });
}

Of course, this is not tested and not the only way, but it should give you an idea :slight_smile:.