file-json-db

Async API

Almost every mutating and reading method has both a synchronous and an asynchronous version. The async versions return Promises and go through the collection’s internal lock/queue so concurrent writes stay safe.

Why both?

Naming convention

Async methods end with Async:

SyncAsync
insertinsertAsync
insertManyinsertManyAsync
findfindAsync
findOnefindOneAsync
updateOneupdateOneAsync
updateManyupdateManyAsync
deleteOnedeleteOneAsync
deleteManydeleteManyAsync
updateFuncupdateFuncAsync
importimportAsync
backup (on db)backupAsync

How the lock works

Each collection maintains a boolean lock and a FIFO queue. When you call an async method:

  1. If the lock is free, the operation runs immediately.
  2. If the lock is held, the operation is pushed onto the queue.
  3. When the current operation finishes, the next queued one starts.

This guarantees that two async writes on the same collection never interleave and corrupt part files or the index.

Examples

// Express-style route
app.post('/users', async (req, res) => {
  try {
    const user = await users.insertAsync(req.body);
    res.status(201).json(user);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// Sequential async work
await users.insertAsync({ name: 'Alice' });
await users.insertAsync({ name: 'Bob' });
const all = await users.findAsync({});
console.log(all.toArray());

// Parallel inserts on *different* collections are fine
await Promise.all([
  users.insertAsync({ name: 'Carol' }),
  orders.insertAsync({ total: 49.99 })
]);

findAsync returns a QueryBuilder

findAsync resolves to a normal QueryBuilder. After that you still call the synchronous terminal methods (toArray, first, count):

const builder = await users.findAsync({ active: true });
const page = builder.sort({ name: 1 }).limit(20).toArray();

When to prefer sync

Rule of thumb In a long-running server or desktop app, prefer the async methods for anything that touches the disk. In a one-shot CLI tool, sync is simpler and perfectly fine.