Search code examples
javascriptecmascript-6commonjsdynamic-import

Importing a file using “import(`./player/${file}`)” doesn’t result in the expected value


I have this piece of code which works on CommonJS but I want to switch my project over to ES6 but I get the error that .bind isn’t a function, so I wonder if there is anyone who knows how I would switch this over.

for (const file of player) {
  const event = import(`./player/${file}`);

  Storage.player.on(file.split(".")[0], event.bind(null, client));
}

Solution

  • You’re using a dynamic import. Take a look at the documentation on MDN Web Docs:

    To dynamically import a module, the import keyword may be called as a function. When used this way, it returns a promise.

    So you have a Promise, not a Function. As always, you can simply use console.log(event); or any other debugging technique to inspect what event actually is.

    If you’re inside an async function or top-level in an ES6 module, you can simply try using the await keyword in front of import. However, you can always use .then to receive the imported value. Make sure to also handle import errors, e.g. using .catch.

    See How to return the response from an asynchronous call.

    As you’re importing things in a loop, consider using asynchronous iteration techniques like Promise.all. player is an iterable; if it’s also an Array you can use the .forEach method and bind all listeners using a dynamic import within the callback. You can definitely use the second argument of Array.from, if that doesn’t work.

    So, here’s my suggestion of how to rewrite this code, although with more context, there may be better ways to deal with the asynchronicity:

    player.forEach(async (file) => Storage.player.on(
      file.split(".")[0],
      (await import(`./player/${file}`)).bind(null, client)
    ));
    

    Besides error handling, all you have left to do is to assert that all imported files actually resolve to a Function, otherwise you still won’t have a .bind method.