0

I wish to get an asynchronous dependency at the top level, without having to use top level awaits.

Currently I am using a temporary hack by declaring getService(), an asynchronous function, in the controller file. However, by doing so I have to call the getService() function for every route that I declare in my controller file.

Here is my current code:

// something.controller.ts

const router = Router();

async function getService() {  // temporary hack
    return await container.getAsync<IService>(TYPES.Service)
}


router.get("/collection",
    paginateCollectionSchema,
    validateRequestSchema,

    async (req, res) => {
        const service = await getService(); // if I have 100 routes, I have do this 100 times
        const paginationSettings = await service.getSome(req.query.limit, req.query.offset);
        const pagination = paginate("/collection", paginationSettings);

        return res.json(pagination)
    },
);


...

export router;

What I hope to achieve is something like this:

// something.controller.ts


const router = Router();

// get service once without using top level await


router.get("/collection",
    paginateCollectionSchema,
    validateRequestSchema,

    async (req, res) => {
        // no need to get service
        const paginationSettings = await service.getSome(req.query.limit, req.query.offset);
        const pagination = paginate("/collection", paginationSettings);

        return res.json(pagination)
    },
);


...

export router;
bik555
  • 13
  • 3
  • Just so you know, there's no point to `return await xxx()`. The `await` adds nothing of value at all. You're still returning a promise from that function. – jfriend00 Dec 12 '22 at 02:52
  • Can't really tell what the question is here. What exactly do you want help with? If an operation is asynchronous, you cannot escape `.then()` or `await` or a callback to get it's asynchronous result. There are no secret handshake ways around that. – jfriend00 Dec 12 '22 at 02:54
  • @jfriend00 I aplogogise if I was not clear in describing my problem. My problem is that I was to avoid calling `getService()` whenever I create a new route: `route.get(...`, `route.patch(...`, etc – bik555 Dec 12 '22 at 03:06

1 Answers1

0

If you have some asynchronous initialization that you would like to complete before your server runs so you can use that asynchronous result as a regular variable in the rest of your server, then you can make that asynchronous call and then don't start your server until the result is available. Then, you can just put it in a variable and reference it as a regular variable from any of the server request handlers.

If you need that value in some other module, then you can make a synchronous getter function that you export that will return the variable (you can't directly export it).

FYI, this type of problem is exactly why top level await was invented to make the solution a lot simpler.

You don't show very much of the structure of your code, but here's the general idea:

// variable at top scope you can use in the rest of the code AFTER
// the server has been started
let mainService;

getService().then(service => {
    mainService = service;
    // don't start your server until you have the service available
    app.listen(...);
}).catch(err => {
    console.log("Failed to start server", err);
});

app.get((req, res) => {
    // can use mainService variable directly here
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thanks, but sometimes I get undefined (Javascript's version of Null Pointer Exception) when I call a method from the service... – bik555 Dec 12 '22 at 04:03
  • @bik555 - I have no idea what that means. You'll have to show actual code. If you do NOT start your server until the service value is set, then there is NO possible way for a request handler to get called before the value is set (because the server isn't started yet). If the problem is something else in side your `getService()` call, then that's nothing we can help you with when you haven't shown any of that code or described any of that problem. – jfriend00 Dec 12 '22 at 04:07