在 node.js 中更正异步函数导出

我的自定义模块代码如下:

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

如果在我的模块之外调用函数,它工作得很好,但是如果我在内部调用,我在运行时就会出错:

(node: 24372)未处理的承诺拒绝警告: 未处理的承诺 拒绝(拒绝 id: 1) : 参考错误: PrintNearestStore 不是 定义

当我把语法改成:

module.exports.PrintNearestStore = PrintNearestStore;


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


}

它在模块内部开始正常工作,但在模块外部失败了——我得到了错误:

(node: 32422)未处理的承诺拒绝警告: 未处理的承诺 拒绝(拒绝 id: 1) : TypeError: mymodule 不是功能

所以我把代码改成:

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


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

现在它在所有情况下都有效: 内部和外部。然而想要理解语义,如果有更美丽和更短的方式来写呢?如何正确定义和使用 异步函数: 内部和外部(导出)模块?

172153 次浏览

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`

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) {


}

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
//
};
export let handlePostStore = async (data) => {
console.log('post');
return data;
};


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


// to call it
handlePostStore(data)

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();