Discord.js Collection object mysteriously clearing out despite being properly initialized

Having trouble with my collections object in the Discord.js library. Working on a command and event handler to populate commands and events based on files in directories. The issue is that the second collection I populate becomes empty after both are set, even though they populate correctly individually within the map function.

If I switch the order of setting the collections, the problem shifts to whichever one is set second. Debugging shows no issues related to directories or imported files, leading me to believe it's a misunderstanding of how collections work on an object.

Any insights on this would be appreciated!

import { Command, Event, Config } from "../Interfaces/index"
import { Client, Collection, Intents } from "discord.js"
import glob from "glob";
import { promisify } from "util";

const globPromise = promisify(glob)

class Bot extends Client {
  public events: Collection<string, Event> = new Collection()
  public commands: Collection<string, Command> = new Collection()
  public aliases: Collection<string, Command> = new Collection()
  public config: Config

  public constructor() {
    super({ ws: { intents: Intents.ALL } })
  }

  public async init(config: Config): Promise<void> {
    this.config = config
    this.login(this.config.token)

    const commandFiles: string[] = await globPromise(`${__dirname}/../Commands/**/*.ts`)
    commandFiles.map(async (filePath: string) => {
      const { command }: { command: Command } = await import(filePath)
      this.commands.set(command.name, command)
      if (command.aliases?.length !== 0) {
        command.aliases?.forEach((alias) => {
          this.aliases.set(alias, command)
        })
      }
    })

    const eventfiles: string[] = await globPromise(`${__dirname}/../Events/**/*.ts`)
    eventfiles.map(async (filePath: string) => {
      const { event }: { event: Event } = await import(filePath)
      this.events.set(event.name, event)
      console.log(this) // Events and commands collection are populated
    })
      console.log(this) // Events collection is empty and commands collection is populated
  }
}

Answer №1

It's important to note that each of the commandFiles and eventFiles items were mapped to a Promise without you realizing it. To ensure that the async function is fully executed before calling console.log(this), you must await the Promises returned by the map function.

To wait for all items returned from the map, enclose the call in Promise.all:

const commandFiles: string[] = await globPromise(`${__dirname}/../Commands/**/*.ts`)
await Promise.all(
    commandFiles.map(async (filePath: string) => {
        ...
    })
);

const eventfiles: string[] = await globPromise(`${__dirname}/../Events/**/*.ts`)
await Promise.all(
    eventfiles.map(async (filePath: string) => {
        ...
    })
);

console.log(this) // collections should now be populated
                  // as you have awaited the results of the `map` functions

Leaving 'dangling' Promises unresolved can often lead to unexpected errors.

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

The Nuxt build is facing issues when connected to domains other than the root domain

Seeking assistance with the Nuxt.js build version, which is functioning properly on my main domain - for instance, my domain is test-domain.com. My build works well here, but on other connected domains like test2-domain.com, the _nuxt folder is not being ...

Is it possible to iterate through TypeScript using both keys and indexes?

Explained in detail at this link, TypeScript introduces a foreach loop: let someArray = [9, 2, 5]; for (let item of someArray) { console.log(item); // 9,2,5 } However, is there a way to access the index/key? I was thinking something along the lines of ...

What is the process for adding new methods to a predefined data type?

Currently, I am utilizing Webpack's require.context in order to eliminate redundancy while importing multiple pages. However, TypeScript is throwing an error stating that Property 'context' does not exist on type 'NodeRequire'.. I ...

Automatically arrange TypeScript import statements in alphabetical order in WebStorm / PhpStorm

I am using tslint with the default config tslint:recommended and I am looking to minimize the number of rules I need to customize. Some rules require that imports be alphabetized: src/core/task/TaskMockDecorator.ts[2, 1]: Imports within a group must be a ...

Tips for modifying HTML elements and navigating to a different webpage

As I delve into the world of front-end web development, I decided to challenge myself with a little exercise by creating a basic HTML form. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ...

Using Jquery and AJAX to dynamically fill out an HTML form based on dropdown selection

My goal is to populate a form on my webpage with information pulled from a MySQL database using the ID of the drop-down option as the criteria in the SQL statement. The approach I have considered involves storing this information in $_SESSION['formBoo ...

Pressing one button triggers a specific function, while pressing another button activates a separate function, but only if the first function has been successfully executed

I am seeking assistance with implementing a script that involves 4 different buttons, each assigned to run distinct functions. Here is the setup: document.getElementById("buttonOne").addEventListener("click", functionOne); document.getElementById("buttonT ...

The error message "TypeError: 'results.length' is not an object" occurred within the Search Component during evaluation

Having trouble with a search feature that is supposed to display results from /api/nextSearch.tsx. However, whenever I input a query into the search box, I keep getting the error message TypeError: undefined is not an object (evaluating 'results.lengt ...

The custom marker created with Leaflet using divIcon does not seem to be styled with the specified

I'm currently working on customizing the leaflet marker using a divIcon and custom HTML. My aim is to have my marker displayed similarly to this example: https://i.sstatic.net/a5RnY.png So far, I've managed to create a marker and a divIcon with ...

Keep retrieving information until the outcome becomes an empty array

I'm currently implementing the Selly API in my project and I've encountered an issue with fetching all products as the Selly API paginates the results. To overcome this, my approach is to fetch all products, store them in an array, and then outp ...

Retrieve the current exchange rate for the specified trading pair in United States Dollars

I am in the process of developing a bot that utilizes the Binance API. I am looking to obtain the USD value for each trading pair similar to what is displayed in their App (refer to screenshot). Is there a method available through their API to accomplish t ...

Looking to transform a nested JSON structure into a visually appealing HTML table with merged rows?

My JSON structure appears as follows: $scope.data = [ { "type":"Internal", "count": 3, "library" : [ { "type":"Library 123", "count": 2, "version" ...

Utilizing Google Places Autocomplete to tailor search outcomes

I'm currently working on customizing the output of my Google Places autocomplete code. Specifically, I want to change the displayed result when a user selects an address from the list. For example, one of the results is: '45 Alexandra Road Holi ...

encountering a problem integrating react-dropzone into a project using react-16.13.1

I'm having an issue adding the package https://www.npmjs.com/package/react-dropzone to my TypeScript React project using Yarn as the package manager. I ran the command yarn add @types/react-dropzone, but it ended up installing a deprecated package h ...

When a property is passed as a prop in a Vue component, it is received

https://jsfiddle.net/2xwo87bs/ In order for Vue to properly handle the object prop that is being passed to the component, it is necessary to first convert the string into an actual object. While in the provided snippet I have used JSON.parse() as a qui ...

Is it possible to perform a local multipleSearch programmatically using free-jqgrid?

Despite spending countless hours and even days searching, I have yet to find a satisfactory solution to my dilemma: All I desire is to utilize the local search/filter capabilities of jqgrid (currently using free-jqgrid 4.9.0) programmatically. I am hopin ...

What exactly is the window object model all about?

While I understand that there is a concept known as the DOM in javascript, I have often wondered why there isn't something similar to a Window Object Model. After all, if you look at the structure of the DOM-tree, it does seem like it could be represe ...

What is the hierarchy of fields in package.json?

After submitting a pull request to a repository to include a typings field in the package.json file, the maintainer suggested the following modification: - "typings": "./src/index.d.ts", - "main": "./src/index.js" ...

Trouble with disabling default actions and transferring text

When the user clicks on loginAccount, the intention is to extract the text from the element with the id input-1 and assign it to username. This same process should occur for password, followed by form submission. However, despite using e.preventDefault() ...

Is it possible to utilize an API response within a conditional statement in NextJS?

I am working on a change password feature that interacts with an API for verification. If the current password entered is incorrect, I want to display an error message. If you have any suggestions on how to proceed or if there are any flaws in my approach ...