98

I had my custom module with following code:

module.exports.PrintNearestStore = async function PrintNearestStore(session, lat, lon) {
...
}

It worked fine if call the function outside my module, however if I called inside I got error while running:

(node:24372) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): ReferenceError: PrintNearestStore is not defined

When I changed syntax to:

module.exports.PrintNearestStore = PrintNearestStore;

var PrintNearestStore = async function(session, lat, lon) {

}

It started to work fine inside module, but fails outside the module - I got error:

(node:32422) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: mymodule.PrintNearestStore is not a function

So I've changed code to:

module.exports.PrintNearestStore = async function(session, lat, lon) {
    await PrintNearestStore(session, lat, lon);
}

var PrintNearestStore = async function(session, lat, lon) {
...
}

And now it works in all cases: inside and outside. However want to understand semantics and if there is more beautiful and shorter way to write it? How to correctly define and use async function both: inside and outside (exports) module?

Aleksey Kontsevich
  • 4,671
  • 4
  • 46
  • 101

5 Answers5

129

This doesn't really have anything to with async functions specially. If you want to call a function internally and export it, define it first and then export it.

async function doStuff() {
  // ...
}
// doStuff is defined inside the module so we can call it wherever we want

// Export it to make it available outside
module.exports.doStuff = doStuff;

Explanation of the problems with your attempts:

module.exports.PrintNearestStore = async function PrintNearestStore(session, lat, lon) {
...
}

This does not define a function in the module. The function definition is a function expression. The name of a function expression only creates a variable inside the function itself. Simpler example:

var foo = function bar() {
  console.log(typeof bar); // 'function' - works
};
foo();
console.log(typeof foo); // 'function' - works
console.log(typeof bar); // 'undefined' - there is no such variable `bar`

See also Named function expressions demystified. You could of course refer to the function if you'd refer to module.exports.PrintNearestStore everywhere.


module.exports.PrintNearestStore = PrintNearestStore;

var PrintNearestStore = async function(session, lat, lon) {

}

This is almost OK. The problem is that the value of PrintNearestStore is undefined when you assign it to module.exports.PrintNearestStore. The order of execution is:

var PrintNearestStore; // `undefined` by default
// still `undefined`, hence `module.exports.PrintNearestStore` is `undefined`
module.exports.PrintNearestStore = PrintNearestStore;

PrintNearestStore = async function(session, lat, lon) {}
// now has a function as value, but it's too late

Simpler example:

var foo = bar;
console.log(foo, bar); // logs `undefined`, `undefined` because `bar` is `undefined`
var bar = 21;
console.log(foo, bar); // logs `undefined`, `21`

If you changed the order it would work as expected.


module.exports.PrintNearestStore = async function(session, lat, lon) {
    await PrintNearestStore(session, lat, lon);
}

var PrintNearestStore = async function(session, lat, lon) {
...
}

This works because by the time the function assigned to module.exports.PrintNearestStore is executed, PrintNearestStore has the function as its value.

Simpler example:

var foo = function() {
  console.log(bar);
};
foo(); // logs `undefined`
var bar = 21;
foo(); // logs `21`
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 1
    Thank You, I see. Just reordered function definition (removed `var`) and `module.exports` now - function definition first. I see that for Internal call function definition order is not important: I have function call BEFORE its definition, however for `module.exports` it matters. – Aleksey Kontsevich Oct 12 '17 at 17:44
  • 2
    @AlekseyKontsevich: FWIW, Line A being *before* line B in the source code doesn't mean that line A is *executed* *before* line B. In the end, the order of execution is the only thing that matters. Of course the function definition has to be evaluated before the function can be called. However, the order of execution might not be obvious in JS due to hoisting. – Felix Kling Oct 12 '17 at 17:47
8

an alternative would be to export like this. // foo.js

export async function foo(){ 
 console.log('I am greatest of all.'); // for the person who reads it, just say it.
}

then use it in other scripts like

import { foo } from './foo'

foo();
rajeshtva
  • 410
  • 6
  • 18
5

Error with first case: PrintNearestStore - Function expression, so this name not available outside.

error with second case: using variable, instead Function declaration. In this case, declaration of variable PrintNearestStore are hoisted, so, you can use this name before line var PrintNearestStore = ..., but in this case value would be undefined.

So, simplest solution change second variant like this:

module.exports.PrintNearestStore = PrintNearestStore;

async function PrintNearestStore(session, lat, lon) {

}
Grundy
  • 13,356
  • 3
  • 35
  • 55
2

Some examples:

module.exports.func1 = async function func1(id) {  // name is preferred by linter
  //
};

module.exports.func1 = async function (id) { // ok
  //
};

module.exports.func1 = async (id) => { // simpler
  //
};
Manohar Reddy Poreddy
  • 25,399
  • 9
  • 157
  • 140
2
export let handlePostStore = async (data) => {
    console.log('post');
    return data;
};

// to import 
import { handlePostStore } from 'your_path_here';

// to call it 
handlePostStore(data)
Julio fils
  • 75
  • 3
  • 1
    Code dumps do not make for good answers. You should explain how and why this solves their problem. I recommend reading, [How do I write a good answer?](https://meta.stackexchange.com/questions/7656/how-do-i-write-a-good-answer-to-a-question) – Amir Dora. Feb 15 '21 at 18:40
  • I got error > export let handlePostStore = async (data) => { ^^^^^^ SyntaxError: Unexpected token 'export' – Nam G VU Aug 02 '23 at 07:54