我已经登陆这个线程,寻找一些类似的东西,并想提出一种解决方案,至少在某些情况下(但请参阅下面的备注)。
用例
我有一个模块,它在加载后立即运行一些实例化逻辑。我确实不喜欢在模块外部调用这个初始化逻辑(与调用 new SomeClass(p1, p2) 或 new ((p1, p2) => class SomeClass { ... p1 ... p2 ... }) 等类似)。
我确实喜欢这个初始化逻辑将运行一次,有点像一个单一的实例化流程,但是每个特定的参数化上下文运行一次。
示例
service.js 具有最基本的范围:
let context = null; // meanwhile i'm just leaving this as is
console.log('initialized in context ' + (context ? context : 'root'));
模块 A:
import * as S from 'service.js'; // console has now "initialized in context root"
模块 B 的作用:
import * as S from 'service.js'; // console stays unchanged! module's script runs only once
到目前为止一切顺利:两个模块都可以使用服务,但只初始化了一次。
问题
如何让它作为另一个实例运行并在另一个上下文中再次初始化自己,比如在模块 C 中?
解决方案?
这就是我正在考虑的:使用查询参数。在服务中,我们将添加以下内容:
let context = new URL(import.meta.url).searchParams.get('context');
模块 C 可以:
import * as S from 'service.js?context=special';
模块将被重新导入,它的基本初始化逻辑将运行,我们将在控制台中看到:
initialized in context special
备注:我自己建议不要过多地练习这种方法,而是将其作为最后的手段。为什么?多次导入的模块更多的是例外而不是规则,因此它有些出乎意料的行为,因此可能会使消费者感到困惑甚至破坏它自己的“单例”范式(如果有的话)。