Search code examples
javascriptpostgresqles6-promise

Array of queries for `for await` loop for postgresql transaction helper


I made a transaction function that simplifies this action for me like this (it working):

export async function transaction(queriesRaw) {
  let allResults = []

  const client = await pool.connect()

  try {
    await client.query('BEGIN')
    var queries = queriesRaw.map(q => {
      return client.query(q[0], q[1])
    })

    for await (const oneResult of queries) {
      allResults.push(oneResult)
    }
    await client.query('COMMIT')
  } catch (err) {
    await client.query('ROLLBACK')
  } finally {
    client.release()
    return allResults
  }
}

And do transactions like this:

let results = await transaction([
            ['UPDATE readers SET cookies=5 WHERE id=$1;', [1]],
            ['INSERT INTO rewards (id) VALUES ($1);', [3]]
          ])

Transaction should do queries one at a time in array index sequence (so rollback to previos values will work correctly) and return in the same order (sometimes i need return values from some queries)

As i understand it starts already in map map function. In for await i just wait for results of it and second query may complete faster that previos.

So how can i fix this?

P.S. Maybe something like new Promise() instead map is the rigth way?


Solution

  • If i got you correctly, Just use a for loop with proper await, instead of a callback style loop.

    So you can wait with the function to return unil everything is chronologically executed, With some thinking, you can easily add aa revoke() function or something..

    
    ...
    export async function transaction(queriesRaw) {
      let allResults = []
    
      const client = await pool.connect()
    
      try {
        await client.query('BEGIN')
    
        for(var i = 0; i < queriesRaw.length;i++) {
            var res = await client.query(queriesRaw[i][0], queriesRaw[i][1])
            allResults.push(res)
        }
    
        await client.query('COMMIT')
      } catch (err) {
        await client.query('ROLLBACK') 
    
        // do you maybe wanna errors to results to?
        // allResults.push(err)
      } finally {
        client.release()
        return allResults
      }
    }
    
    

    Info,

    Have a look at for example async module, or something similar. So you will not have to think about things like this.