在 TypeScript 中实现单例模式,你可以使用模块模式来确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。以下是一个简单的单例模式的 TypeScript 实现:
首先,你可以在 db.ts
文件中创建一个单例的 Knex
实例:
// db.ts
import { Knex } from 'knex';
const config: Knex.Config = {
client: 'sqlite3',
connection: {
filename: './data.db',
},
// 其他配置项...
};
let knexInstance: Knex | null = null;
function getKnexInstance(): Knex {
if (!knexInstance) {
knexInstance = Knex(config);
}
return knexInstance;
}
export default {
getKnexInstance,
};
然后,在你的代码中使用这个单例:
// 其他文件
import db from './db';
const { getKnexInstance } = db;
const knexInstance = getKnexInstance();
// 使用 knexInstance 进行数据库操作
knexInstance.raw('some sql query').then(result => {
// 处理结果
}).catch(error => {
// 处理错误
});
注意,在 db.ts
中我们导出了一个对象,它有一个方法 getKnexInstance
,该方法会返回 Knex
的单例实例。每次调用 getKnexInstance
时,都会检查 knexInstance
是否已经存在,如果不存在则创建它。
这样,无论你在项目的哪个部分需要 Knex
实例,你都可以从 db.ts
中获取它,并确保你得到的是同一个实例。
此外,你提到想要直接解构 knexInstance
,但如果你想保持单例模式,则不能直接解构它,因为这会导致每次导入时都创建一个新的局部变量,而不是使用全局的单例实例。通过 getKnexInstance
函数,你可以确保始终获取的是相同的单例实例。
如果你确实想要直接解构出 knexInstance
,你可以考虑使用 TypeScript 的立即执行函数表达式 (IIFE),但这样做将不再需要 getKnexInstance
方法,因为 knexInstance
已经在模块作用域内被创建:
// db.ts
import { Knex } from 'knex';
const config: Knex.Config = {
client: 'sqlite3',
connection: {
filename: './data.db',
},
// 其他配置项...
};
const knexInstance: Knex = (function() {
const instance = Knex(config);
return instance;
})();
export { knexInstance };
然后你可以在其他文件中这样使用:
// 其他文件
import { knexInstance } from './db';
// 直接使用 knexInstance 进行数据库操作
knexInstance.raw('some sql query').then(result => {
// 处理结果
}).catch(error => {
// 处理错误
});
但是,请注意,这种方法将使得 knexInstance
在模块加载时立即创建,而不是在第一次调用时。在大多数情况下,这仍然有效,但如果你需要在模块加载时执行某些逻辑(例如,基于配置或环境变量决定是否创建实例),那么第一种方法可能更适合你。
db.ts
其它文件