JavaScript中如何让save方法等待collection.create()完成后执行
Got it, the problem here is that your collection.create() call runs asynchronously in the constructor, but your save method might execute before that operation finishes—leading to crashes when trying to interact with a collection that isn't ready yet. Let's fix this properly with a couple of solid approaches:
方案一:子类内维护初始化Promise,确保save等待完成
We can add a ready Promise to your UserRepository that resolves once the collection is confirmed to exist (either created successfully or already present). All collection-dependent methods like save will await this Promise first:
class UserRepository extends BaseRepository<User> { private readonly ready: Promise<void>; constructor() { super(); this.collection = this.db.collection('users'); // Wrap collection creation logic into the ready Promise this.ready = this.ensureCollectionExists(); } private async ensureCollectionExists(): Promise<void> { try { const res = await this.collection.create(); if (res.code === 200) { console.log('Users collection created successfully'); } } catch (err) { if (err.code === 409) { console.log('Users collection already exists, no action needed'); } else { // Don't swallow unexpected errors—let them propagate so you can handle failures throw err; } } } // Override save to wait for collection readiness before proceeding async save(entity: User): Promise<void> { await this.ready; // Delegate to parent class's save logic await super.save(entity); } } class BaseRepository<T> { protected db: /* Your DB client type */; protected collection: /* Your collection type */; async save(entity: T): Promise<void> { // Example parent save logic—adjust to your actual implementation await this.collection.insertOne(entity); } }
方案二:抽离初始化逻辑到BaseRepository(适合多Repository场景)
If you have multiple repositories that need this collection readiness check, move the logic up to the BaseRepository to avoid code duplication:
class BaseRepository<T> { protected db: /* Your DB client type */; protected collection: /* Your collection type */; private readonly ready: Promise<void>; constructor(collectionName: string) { this.db = /* Initialize your DB client here */; this.collection = this.db.collection(collectionName); this.ready = this.ensureCollectionExists(); } private async ensureCollectionExists(): Promise<void> { try { const res = await this.collection.create(); if (res.code === 200) { console.log(`Collection "${this.collection.name}" created successfully`); } } catch (err) { if (err.code === 409) { console.log(`Collection "${this.collection.name}" already exists`); } else { throw err; } } } // Base save method automatically waits for collection readiness async save(entity: T): Promise<void> { await this.ready; await this.collection.insertOne(entity); } } class UserRepository extends BaseRepository<User> { constructor() { // Pass collection name to parent constructor super('users'); } }
Why this works
- The
readyPromise acts as a gatekeeper: any method that needs to interact with the collection will wait until the collection is confirmed to exist. - Constructor can't be async, so wrapping the async initialization logic into a Promise is the cleanest way to handle this.
- We don't swallow unexpected errors (like permission issues or DB connection failures)—this ensures you catch and handle real problems instead of letting the app crash silently later.
内容的提问来源于stack exchange,提问作者Almis

