Search code examples
javascriptnode.jsasync-awaites6-modulescommonjs

Use top level await in CJS script and import a ES module


I was fixing a vulnerable jar for my CJS service which was earlier being used by require keyword:

helper.js:
----------
const foo = require('formidable');
function saveFile(req, location) {
  return new Promise((resolve, reject)=> {
   // use foo...
 }
}

index.js:
---------
helper = require('./helper')
// use helper...

The latest version of formidable is in ES so require does not work. I tried searching and found that dynamic import might solve this.

  1. Brute force approach didn't work. Compilation was success but while running it said constructor not found while instantiating formidable.
helper.js:
----------
const  foo = import('formidable');
function saveFile(req, location) {
  return new Promise((resolve, reject)=> {
   // use foo...
 }
}
  1. Added await to first line const foo = await import('formidable'); Doesnt work get an error SyntaxError: await is only valid in async function
  2. Tried making saveFile function async too but doesn't work. same error as in 2.

Now I cant covert my whole service to module by adding type=module in package.json as that will impact 100s of files. Is there any other approach to just import the new ES module formidable and use it without changing existing behavior too much ?

P.S: Using Node 16.1. Pls let me know if more info is needed. Happy to mark duplicate if similar exists.


Solution

  • Ideally, you should write new code in ES modules. They seem to just be the better of options nowadays.

    Anyway, you can use .then():

    const fooPromise = import('formidable');
    
    function saveFile(req, location){
        return new Promise((rslv, rjct) => {
            fooPromise.then(foo => {
                // Do stuff with foo.
            });
        };
    }
    

    Update

    Now that I think of it, you can actually make saveFile() async and await the fooPromise:

    async function saveFile(req, location) {
        const foo = await fooPromise;
        // Do stuff with foo.
    }