为了在模块之间共享数据,通常的模式是将数据封装到一个公共(public)模块中,然后将其导入到其他模块中。
在我的例子中,要共享的数据是一个记录器,需要在使用前对其进行初始化。我在应用程序的入口点调用 init()
。
// main.js
let logger = require('@my/logger');
logger.init({...});
let xxx = require('./moduleX');
let yyy = require('./moduleY');
在其他模块中,可以使用初始化的logger:
// moduleX.js
let logger = require('@my/logger');
const log = logger('moduleX');
function x() {
log.debug('some msg');
}
以上代码在 node.js 中运行良好。但是如果我更改为 ES6 模块语法,它就不起作用,因为 ES6 模块导入被提升了。
// main.js
import {logger} from '@my/logger';
logger.init({...}); // this line is run after import moduleX
import {x} from './moduleX';
// moduleX.js
import {logger} from '@my/logger';
const log = logger('moduleX'); // logger is not initialized !
export function x() {
log.debug('some msg');
}
使用ES6模块,如何初始化一些数据并共享给其他模块?
有一个类似的question但答案不适合我的情况。
更新:
一些答案建议将访问共享数据的代码放入函数中,这样代码就不会在模块加载时立即被调用。但是如果我真的需要在模块加载期间访问它怎么办?我更新了我的代码以演示用例——如果不将 log
作为模块范围 const,那么在每个函数中调用 logger(name)
就太简单了。
最佳答案
最后我按照@PaoloMoretti 在他的评论中提到的方式解决了它。
在我的应用程序中编写一个模块来为我的应用程序初始化记录器:
// logger_init.js
import {logger} from '@my/logger';
logger.init({...});
在应用程序的入口点导入一次初始化模块,然后再导入任何其他使用记录器的模块。它保证在加载其他模块之前完成初始化。
// main.js
import './logger_init';
import {x} from '@my/other_module';
import {y} from './module_in_myapp';
其他模块可以直接使用初始化的logger:
// @my/other_module
import {logger} from '@my/logger';
const log = logger('moduleX'); // logger has been initialized
export function x() {
log.debug('some msg');
}
依赖树是:
<init>
myapp --+--> logger_init ------------> @my/logger
| <use> ↑
+--> module_in_myapp -----------+
| <use> |
+--> @my/other_module ----------+
为什么我不采用添加初始化并返回记录器的包装器模块的方式(如 Bergi 的回答),因为使用记录器的模块可能是不在我的应用程序中的可重用模块。
关于javascript - ES6 : share data between modules,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34226229/