1

I have to export a result of async function from a Javascript file. Right now, When I export it, I am getting a promise which needs then() function in each file wherever we want to import that file. Due to this issue, I need to resolve the exported results in each file where we are importing it. I simply want the results of the async operation not the promises. How can we achieve it ?

mainfile.js

    const getAllDatabases = async(dbconnection) => {
      const results = await dbconnection.query(
        `SELECT name FROM master.dbo.sysdatabases`
      );
      return results;
    }
    
    module.exports = getAllDatabases();

otherfile.js

    const mainfile = require("mainfile");
    mainfile.then((reponse)=>{
        reponse[db].Table.Operation();
    });
bguiz
  • 27,371
  • 47
  • 154
  • 243
Suraj Singh
  • 351
  • 3
  • 10
  • 1
    https://github.com/tc39/proposal-top-level-await is finished, and usable in all modern browsers, plus node (even LTS), afaik. You need esm though, not cjs. – ASDFGerte Apr 07 '22 at 14:06
  • @suraj-singh, an async function must always return Promise only. If you want to use multiple databases in this project, I would suggest using different DB refs ( maybe in different files and manage each connection separately). – Devesh Apr 07 '22 at 14:14
  • @DeveshShukla I am using MSSQL server. What I am doing is whenever I restart the node server I connect all databases and put them into array of connection. That array is being used by passing the db name as array key. Well, that is not the problem. The problem is to do some trick which only export the promise result. – Suraj Singh Apr 07 '22 at 14:18
  • @ASDFGerte Could you share some code regarding the same implementation. – Suraj Singh Apr 07 '22 at 14:19

1 Answers1

1

You can't do that with CommonJS (what you're using now). You can export the promise just fine, but anything using that export has to consume the promise (that's not "resolving" it, resolving is a different thing; I've written up some terminology here). That should be fine in the general case, it's not like you're re-running a process or anything, you're just accessing the fulfillment value the promise already has. Alternatively, you could export an object (well, a different object) and fill in the names as properties on that object, but any code using the object would have to allow for the possibility it's not filled in yet. Which is the whole point of promises: to standardize situations like that.

With ESM, you can use top-level await, which has good browser support, support in Node.js, and support in most modern bundlers. That would let you hold up the loading of your module until the asynchronous process completes, allowing you to export the value you got:

// mainfile.js - 
export const allDatabases = await dbconnection.query(
    `SELECT name FROM master.dbo.sysdatabases`
);

// otherfile.js - 
import { allDatabases } from "./mainfile.js";
allDatabases[db].Table.Operation();

mainfile.js doesn't finish loading until that promise is fulfilled (and doesn't finish at all if the promise is rejected; you could handle that with a try/catch).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • The way you shared is just a work around using setTimeout(). I don't think that is good to implement. – Suraj Singh Apr 07 '22 at 15:03
  • @SurajSingh - I think I must be misunderstanding your comment. Are you saying that you think top-level `await` is the same as a `setTimeout` hack?! – T.J. Crowder Apr 07 '22 at 16:26
  • Yes, They are using sertimeOut only. I looked a the link you shared - https://github.com/tc39/proposal-top-level-await. – Suraj Singh Apr 08 '22 at 08:11
  • @T.H.Crowder Can you share me implemented code of it as per my reference. – Suraj Singh Apr 08 '22 at 09:54
  • @SurajSingh - Top-level `await` has nothing whatsoever to do with `setTimeout`. (I don't understand why they use `setTimeout` in some of the examples.) If it were just a hack like that, there's no chance it would have made it through the proposal process. Instead, it's a genuine mechanism for delaying module loading until a promise settles. [Here's an example](http://farsightsoftware.com/tla/) that reads a large-ish file, holding up the module loading process until the file is loaded. (I wanted to do that on CodeSandbox, but their ESLint config is out of date.) – T.J. Crowder Apr 08 '22 at 12:14
  • @T.H.Crowder Could you share me the code of this link - http://farsightsoftware.com/tla , what you have shared above. – Suraj Singh Apr 08 '22 at 12:49
  • @SurajSingh - You should be able to get it from the link itself. This is the web, remember? You can download the files. – T.J. Crowder Apr 08 '22 at 12:49
  • @T.H.Crowder Yes, I got it. But I want to achieve it using CommonJS. Is there something that we could use for CommonJS? – Suraj Singh Apr 12 '22 at 09:19
  • 1
    @SurajSingh - As I said above, you can't. CommonJS just doesn't have the concept of top-level `await`, and it can only export values. You could wait for the promise to settle and then add the value to `module.exports`, but it's entirely likely that other modules trying to import it would have already loaded (and thus not gotten the export). Just export the promise, and use it in the modules. – T.J. Crowder Apr 12 '22 at 09:27