Navigating S3 bucket with JavaScript: A step-by-step guide

After researching various tutorials and examples, I attempted to replicate their implementations without success. My current issue involves storing a list of keys from an S3 bucket in order to iterate through them within my Vue application. In the code snippet provided, there are 3 console.log statements that attempt to display the value of files. Surprisingly, the first log outputs the expected result, while the second one displays [], and the third does not print anything at all. This inconsistency suggests that the value of files is not persisting outside the s3.listObjectsV2() function, thereby hindering access to the actual files in the app itself.

let AWS = require("aws-sdk");
AWS.config.update({
  accessKeyId: process.env.VUE_APP_ACCESS_KEY,
  secretAccessKey: process.env.VUE_APP_ACCESS_KEY,
  region: "us-east-1",
});
let s3 = new AWS.S3();

let params = {
  Bucket: "my-bucket",
  Delimiter: "",
};

let getS3Files = () => {
  let files = [];
  s3.listObjectsV2(params, function (err, data) {
    if (data) {
      data.Contents.forEach((file) => {
        files.push({
          fileName: file.Key,
          fileDate: file.LastModified,
        });
      });
      console.log(files);
    }
  });
  console.log(files);
  if (files.length > 0) {
    files = files.sort((a, b) => b.fileDate - a.fileDate);
    console.log(files);
  }
  return files;
};

getS3Files();

Answer №1

The reason for the issue is that you are not allowing enough time for the s3.listObjectsV2 function to complete fetching its data. Even though it may not appear as a function that requires waiting, it actually needs time to communicate with s3 and retrieve the requested data.

In the snippet of code provided, the second console.log is likely to execute before the first one, resulting in an empty files array. Consequently, when checking for elements in the files array during the third log, it will also return false since at that point files = [].

To address this, it is essential to wrap the process within a Promise and await its completion.

let getS3Files = async () => {
  let files = [];

  await new Promise(function (resolve, reject) {
    s3.listObjectsV2(params, function (err, data) {
      if (data) {
        data.Contents.forEach((file) => {
          files.push({
            fileName: file.Key,
            fileDate: file.LastModified,
          });
        });
        console.log(files);
        resolve();
      } else {
        reject(err);
      }
    });
  });

  console.log(files);

  if (files.length > 0) {
    files = files.sort((a, b) => b.fileDate - a.fileDate);
    console.log(files);
  }

  return files;
};

await getS3Files();

Answer №2

While I may not have much experience with the s3 api, it's important to note that listObjectsV2 is an asynchronous operation. Therefore, if you're finding that `files` is empty, it could be due to it being executed before the asynchronous call has completed.

To address this issue, consider implementing the following:

let AWS = require("aws-sdk");

AWS.config.update({
  accessKeyId: process.env.VUE_APP_ACCESS_KEY,
  secretAccessKey: process.env.VUE_APP_ACCESS_KEY,
  region: "us-east-1",
});

let s3 = new AWS.S3();
let params = {
  Bucket: "my-bucket",
  Delimiter: "",
};

let getS3Files = (callback) => {
  s3.listObjectsV2(params, function (err, data) {
    callback(data);
  });
};

getS3Files((data) => {
  const files = data.Contents.map((file) => ({
    fileName: file.key,
    fileDate: file.LastModified,
  })).sort((a, b) => b.fileDate - a.fileDate);

  return files;
});

Remember, the getS3Files function expects a callback containing the data which you can then process within the function.

If you require further insight on handling asynchronous calls, you might find this question helpful:How do I return the response from an asynchronous call?

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing React Refs to Retrieve Value from HTML Select Element

I am currently working on a form that includes the use of an HTML select element. <select className="form-control" id="ntype" required > <option value = "">None</option> <option value = "1">1</option> < ...

Tips for utilizing formidable with NextJS 13 API for image uploading and resolving request errors

I've been working on integrating image uploading functionality into my application. I'm currently using NextJS version 13.4.4 along with formidable@v3. However, whenever I attempt to upload an image, I encounter the following error: error TypeE ...

initialize input data in vue

How can I set a default value for an input in a date picker using Vue JS? I have tried setting the data but it's not showing up. When I inspect the element, I see this code: https://i.stack.imgur.com/fQDLL.png Here is my script: new Vue({ e ...

Steps to generate a new page when submitting a form:

When a form is submitted, I am aiming to generate a fresh page each time. This new page will serve as an order status tracker that will be updated regularly. Essentially, my goal is for users to see a confirmation page for the form submission and have acce ...

Navigating with Vue.js using programmatic methods while passing props

I am working with a Vue component that includes a prop called 'title' like this: <script> export default { props: ['title'], data() { return { } } } </script> After completing a specific action, I need to pro ...

Selenium Webdriver failing to select menuitem using text, xpath, or ID

Currently, I have some HTML code embedded in a SharePoint page that appears as follows: <span style="display:none"> <menu type='ServerMenu' id="zz28_RptControls" largeIconMode="true"> <ie:menuitem id="zz29_AddColumn" type="optio ...

Getting an error that reads, "Unable to read properties of null (reading 'uid')," but surprisingly, the application continues to function properly

After logging out, I encounter the following error: (Uncaught TypeError: Cannot read properties of null (reading 'uid')). However, my application functions as intended. During the logout process, I delete an API access token from the user docume ...

Reactjs, encountering a hitch in utilizing material UI: Incompatible hook call detected

As a newcomer to React, I decided to incorporate Material UI components into my project. After installing the components locally using npm install and importing them into my project, I encountered an error when trying to run start: Error: Invalid hook call ...

Creating an input field within a basic jQuery dialog box is not possible

Can anyone assist me in adding an input box to my dialog box? I am working with jquery-ui.js. Here is the code I currently have: $(document).on("click",".savebtn",function(). { var id = $(this).attr("id"); $.dialog({ ...

How to eliminate grid lines and labels from Chart.js graphs?

Is there a way to hide the grid lines in the Radar chart using chart.js v2 for react? Desired Result, I am looking to hide the inner lines and numbers while keeping the outermost line visible. I tried to implement the following code, but it resulted in a ...

Express application functioning solely on the local server

Attempting to create a basic API for a project, I tested the sample code using Postman on two different machines. Surprisingly, when the code is executed on my local machine, it returns the expected response; however, running it on a remote Ubuntu server f ...

Looking for a slideshow with interactive play buttons?

Looking for a slideshow similar to the one on the homepage of this site: Has anyone ever used a slideshow like that before? Any other references or help would be appreciated! ...

Is there a way to ensure that my code waits for a function to finish running before proceeding with the rest

Currently working on a Discord bot project and getting stuck on this particular section... Discord is a messaging platform where users can create servers and channels to communicate with each other. In addition, there are bots that can be programmed to pe ...

The command npm start seems to be unresponsive when trying to run a project created

I've scoured the depths of the internet in search of a solution to my problem, but to no avail. Below are the commands I have executed: C:\Users\Angengos>create-react-app learn-react Creating a new React app in C:\Users\Angeng ...

Navigating through the img src using JavaScript

Currently, I am working on a task that involves the following code snippet: <input type="file" id="uploadImage" name="image" /> <input type="submit" id="ImageName" name="submit" value="Submit"> My goal is to have the path of the selected imag ...

Froala - response in JSON format for uploading images

I have integrated the Froala editor into my website. The image upload feature of this editor is functioning properly, but I am facing issues with the response. As per the documentation provided: The server needs to process the HTTP request. The server mu ...

Calculate the sum of numbers entered in a textarea using JavaScript for each line break

I'm working with a textarea that contains the following text: link|10000 link|25000 link|58932 My goal is to eliminate everything before the "|" on each line and then calculate the total sum of all the numbers. If anyone can provide assis ...

Launch an Android application directly from a web browser upon the webpage's loading

When a user visits www.example.com/myApp, I want my app to open automatically without any click required. I have attempted the following methods: window.onload = function () { window.location.replace("intent://something#Intent;scheme=myapp;packag ...

What's causing this sluggish performance?

I'm in the process of developing a Google Chrome extension and I can't help but wonder why window.onload = loadPage; function loadPage() { document.getElementById('nav-robux-amount').innerHTML = '0'; console.log(" ...

Finding the right dropdown option by matching text

Is it possible to choose a dropdown option based on its text? Here is the HTML code snippet that demonstrates this: <li title="Add Page" class="dropdown-header ng-scope" data-ng-if="selectedPage">Add Page</li> <li title="Add page before t ...