1

I have the below code and want to export the handler using module.exports.handler. Since start() is an async function and the handler is defined inside of it, I can't export it properly by using the below code. I tried using top-level await for start() and got an error. Can I know another way to achieve this? Thanks in advance.

//index.ts

import serverless from 'serverless-http';

let handler;
const start = async (): Promise<void> => {
    
    //some function calls with await

    const server = express();
    //server.use()

    handler = serverless(server);
};

start().then(() => {
    console.log(handler) //[AsyncFunction (anonymous)]
});
console.log(handler) //undefined

module.exports.handler = handler;

Btw, I need to use handler in my serverless.yml

service: rest-server
provider:
  name: aws
  runtime: nodejs12.x
  region: eu-west-1
  environment: ${file(serverless.env.yml)
  stage: dev
  memorySize: 128
functions:
  h5p:
    handler: src/index.handler
    events:
      - http: ANY /
      - http: 'ANY {proxy+}'
plugins:
  - serverless-plugin-typescript
  - serverless-offline
Rukshan Jayasekara
  • 1,945
  • 1
  • 6
  • 26
  • 2
    why not export the `start` function and call `start` where you need to the `handler`? – Yousaf Jun 25 '21 at 09:16
  • 1
    you can't export a value that isn't available immediately - you can export a Promise though ... `module.exports.handlerPromise = start()` ... – Jaromanda X Jun 25 '21 at 09:22
  • @JaromandaX In general, yes, but I suppose serverless won't like that – Bergi Jun 25 '21 at 09:42
  • @Bergi - yeah, I don't know `serverless` :p – Jaromanda X Jun 25 '21 at 09:43
  • 1
    @Bergi according to their [documentation](https://www.serverless.com/plugins/serverless-http) serverless allows the handler to be async, so one can use that – A_A Jun 25 '21 at 09:45

1 Answers1

1

You can make a new handler, that waits until starting is done, and then calls the original handler. This only requires, that the exported handler function is allowed to be async.

const finishedStarting = start()

module.exports.handler = (...args) => finishedStarting.then(() => handler(...args));
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
A_A
  • 1,832
  • 2
  • 11
  • 17
  • 2
    Don't make it so complicated with managing `startingCallbacks` yourself. Just use `const handlerPromise = start(); module.export.handler = async (...args) { const handler = await handlerPromise; return handler(...args); };` (or `….handler = (...args) => handlerPromise.then(handler => handler(...args));` which is even a bit shorter) – Bergi Jun 25 '21 at 09:49
  • Thanks for that suggestion, I didn't know that one could use `.then` multiple times on a Promise – A_A Jun 25 '21 at 10:00
  • I tested this solution with a couple of endpoints. Seems like finally I can go with this. Thanks for your time @A_A :) – Rukshan Jayasekara Jun 25 '21 at 10:09