- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在 Javascript 中定义一个单例,以便能够从不同的文件中使用。
class DataService {
constructor(options) {
this.models = options.models ;
this.data = {};
this.refresh();
}
refresh() {
Promise.all([
this.models.DATA.model.findAll({
raw: true,
attributes: ['key', 'value']
})
]).then(([data]) => {
this.data = this.parseData(data);
});
}
parseData(data) {
data.map(x => {
this.data[x.key] = JSON.parse(x.value);
});
return this.data;
}
}
module.exports = (options) => { return new DataService(options) };
我希望能够像这样导入模块
const data = require('dataService')(options);
console.log('data.example', data.example);
我不确定是否可以这样做,因为我使用的是异步方法,并且当我打印日志时数据还没有准备好。
最佳答案
您可以利用模块在所有模块中实现类单例模式的方法是直接导出一个实例。
这样做的原因是 require
在第一次导入后缓存导出,因此将在所有后续导入中返回该实例。
现在您正在导出一个函数,尽管它始终是相同的函数,但它具有始终实例化您的类的新实例的能力,因此打破了您想要实现的单例模式约束(单个实例跨模块)
因为您想在外部指定单例实例化选项,所以您可以通过对代码进行最少更改来实现此目的的一种方法是让导出的函数返回一个实例(如果它已经存在),而不是实例化一个新实例:
let instance; // all files will receive this instance
module.exports = (options) => {
if (!instance) {
// only the first call to require will use these options to create an instance
instance = new DataService(options);
}
return instance;
}
这意味着所有执行 require('dataService')(options)
的文件都将接收相同的实例,无论哪个文件首先导入模块,谁的实例化选项都将应用。
请注意,所有后续调用仍必须采用 require('dataService')()
的形式(注意额外的调用),这看起来像是一种代码味道并且会使代码更难理解。
为了使代码更具可读性,我们可以添加一些冗长的内容:
let instance; // all files will receive this instance
module.exports = {
getInstance(options) {
if (!instance) {
// only the first call to getInstance will use these options to create an instance
instance = new DataService(options);
}
return instance;
}
}
可以这样使用:
const instance = require('dataService').getInstance(options);
const instance = require('dataService').getInstance();
const instance = require('dataService').getInstance();
另一个步骤可能是通过在运行时告诉程序员他们是否错误地使用 API 来使代码更容易被滥用:
if (!instance) {
instance = new DataService(options);
} else if (options) {
// throw error on all subsequent calls with an options arg `require('dataService')(options)`
throw Error('Instance is already instantiate with `options`')
}
return instance;
这不会使代码更具可读性,但会使其更安全一些。
如果我们将您的 API 解释为“任何时候传递选项,我们都应该实例化一个新的单例”,那么您可以考虑维护一个实例集合,通过一些 id 检索(或者甚至可能是选项本身的内存引用) ):
let instances = new Map();
module.exports = (options) => {
if (!instances.has(options.id)) {
instances.set(options.id, new DataService(options));
}
return instances.get(options.id);
}
您的单例中有异步代码这一事实应该无关紧要。时间不是单例的属性,要求只有一个实例。
话虽如此,您可能想要考虑实际返回在您的方法中创建的 promise ,以便您可以正确地链接它们或等待它们:
class DataService {
constructor(options) {
this.models = options.models ;
this.data = {};
this.refresh();
}
refresh() {
return Promise.all(/* ... */).then(/* ... */);
//^^^^^^ return the promise chain so we can react to it externally
}
// ...
}
(async () => {
await new DataService().refresh(); // now you can do this
})()
关于Javascript 将带有参数的单例定义为模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54015088/
单向链表 单向链表比顺序结构的线性表最大的好处就是不用保证存放的位置,它只需要用指针去指向下一个元素就能搞定。 单链表图解 图画的比较粗糙,简单的讲解一下: 上面四个长方形,每个长方
使用TCP,我正在设计一些类似于next的程序。 客户端在许多线程中的接收正在等待一台服务器的发送消息。但是,这是有条件的。 recv正在等待特定的发送消息。 例如 客户 thread 1: recv
我正在编写正则表达式来验证电子邮件。唯一让我困惑的是: 顶级域名可以使用单个字符吗?(例如:lockevn.c) 背景:我知道顶级域名可以是 2 个字符到任意字符(.uk、.us 到 .canon、.
是否可以在单个定义中定义同一 Controller 的多个路由? 例如: 我想要一个单一的定义 /, /about, /privacy-policy 使用类似的东西 _home: pat
我正在使用 objective-c开发针对 11.4 iOS 的单 View 应用程序,以及 Xcode版本是 9.4.1。 创建后有Main.storyboard和LaunchScreen.stor
我一直在尝试在 shell 程序中实现管道结构,如果我执行简单的命令(例如“hello | rev”),它就可以工作 但是当我尝试执行“head -c 1000000/dev/urandom | wc
此表包含主机和接口(interface)列UNIQUE 组合* 编辑:这个表也有一个自动递增的唯一 ID,抱歉我应该在之前提到这个 ** | host.... | interface..... |
我想将具有固定补丁大小的“std filter”应用于单 channel 图像。 也就是说,我希望 out[i,j] 等于 img[i,j] 附近的像素值的标准值。 对于那些熟悉 Matlab 的人,
假设我想进行网络调用并使用 rx.Single,因为我希望只有一个值。 我如何应用replay().autoConnect() 这样的东西,这样当我从多个来源订阅时网络调用就不会发生多次?我应该使用
我将图像从 rgb 转换为 YUV。现在我想单独找到亮度 channel 的平均值。你能告诉我如何实现这一目标吗?此外,有没有办法确定图像由多少个 channel 组成? 最佳答案 你可以这样做: #
在比较Go和Scala的语句结束检测时,我发现Scala的规则更丰富,即: A line ending is treated as a semicolon unless one of the foll
在IEEE 1800-2005或更高版本中,&和&&二进制运算符有什么区别?它们相等吗? 我注意到,当a和b的类型为bit时,这些coverpoint定义的行为相同: cp: coverpoint a
我正在使用Flutter的provider软件包。我要实现的是为一个 View 或页面提供一个简单的提供程序。因此,我在小部件中尝试了以下操作: Widget build(BuildContext c
我正在尝试在 cython 中使用 openmp。我需要在 cython 中做两件事: i) 在我的 cython 代码中使用 #pragma omp single{} 作用域。 ii) 使用#pra
我正在尝试从转义字符字符串中删除单引号和双引号。它对单引号 ' 或双自动 " 不起作用。 请问有人可以帮忙吗? var mysting = escapedStr.replace(/^%22/g, '
我正在尝试在 cython 中使用 openmp。我需要在 cython 中做两件事: i) 在我的 cython 代码中使用 #pragma omp single{} 作用域。 ii) 使用#pra
我正在使用 ANT+ 协议(protocol),将智能手机与 ANT+ USB 加密狗连接,该加密狗通过 SimulANT+ 连接到 PC。 SimulANT+ 正在模拟一个心率传感器,它将数据发送到
有人可以解释/理解单/多线程模式下计算结果的不同吗? 这是一个大约的例子。圆周率的计算: #include #include #include const int itera(100000000
我编写了一个粗略的阴影映射实现,它使用 6 个不同的 View 矩阵渲染场景 6 次以创建立方体贴图。 作为优化,我正在尝试使用几何着色器升级到单 channel 方法,但很难从我的着色器获得任何输出
尝试使用 Single-Spa 构建一些东西并面临添加到应用程序 AngularJS 的问题。 Angular2 和 ReactJs 工作完美,但如果添加 AngularJS 并尝试为此应用程序使用
我是一名优秀的程序员,十分优秀!