Search code examples
javascriptpostgresqlpg-promise

Using Promise.all inside a transaction / task vs using t.batch in pg-promise


The documentation here clearly outlines that it is a bad practice to write

Promise.all(data.map(d => db.none('insert into...', d)))

which is querying against root database protocol. Hence it is better to write

db.task(t => t.batch(data.map(d => t.none('insert into...', d))));

However, is it wrong to write this if I do not intend to use BatchError or query duration (ref)?

db.task(async t => {
  await Promise.all(data.map(d => t.none('insert into...', d)));
});

By the looks of it, it still uses shared connection protocol instead of root connection.


Solution

  • The coming of ES7 with async/await to the scene, dissipated the need for putting queries in a batch.

    You can simply do this instead:

    await db.task(async t => {
        await forEachAsync(data, d => t.none('insert into...', d));
    });
    

    or just return the result:

    await db.task(t => forEachAsync(data, d => t.none('insert into...', d)));
    

    That would need async for-each function like this:

    async function forEachAsync(data, cb) {
        for (let i = 0; i < data.length; i ++) {
            await cb(data[i], i, data);
        }
    }
    

    But normally, you do not need any of these when executing an array of inserts, because for that you should be using multi-row inserts instead.