Exception handling and releasing of OracleDB connection Before I start implementing several REST API service endpoints, I'd like to make sure that I'm not doing it totally wrong.

/**
 * GET /api/test
 * Test API example.
 */
export let getTest = (req: Request, res: Response, next: NextFunction) =&gt; {
    // const token = req.user.tokens.find((token: any) =&gt; token.kind === "facebook");
    const db = new Database();

    db.getConnection()
        .then(con =&gt; {
            con.execute('SELECT * FROM BTO_MDS.AlARMS', {}, { maxRows: 22000 })
                .then(result =&gt; {
                    con.release();
                    res.json({data: result.rows});
                })
                .catch(ex =&gt; {
                    con.release();
                    res.status(500).json({message: ex.message});
                });
        })
        .catch(ex =&gt; {
            res.status(500).json({message: ex.message});
        });

};



Is the connection always released properly, or have I forgotten something?
What seems a bit messy is that I need to release the connection two times, and that I have two catch'es, since I cannot release the connection in the second catch.


For completeness: Database is simply a wrapper that contains the connection string configuration and returns a reference to a new connection:

import * as oracledb from 'oracledb';
import { IConnectionPool } from 'oracledb';

const config = {
    user: 'user',
    password: 'pw',
    connectString: 'databaseNameFromTNSNames',
    poolMax: 16
};

export default class Database {
    private pool: IConnectionPool;    
    constructor() {  
    }

    public createPool(): void {
        oracledb.createPool(config).then(conpool =&gt; {
                this.pool = conpool;
                console.log('Connection Pool created!');
            },
            err =&gt; {
                console.log('Error creating pool!');
            });
    }

    public getConnection() {
        return oracledb.getConnection();
    }    
}
There really isn't too much to say about your posted code.

Answering your specific question: 

Yes, the connection will always be released as either your then or your catch method will always run. However, if res.json({data: result.rows}); (or more complex code once you have developed further) throws, your code will try to release the connection twice. This will likely result in an uncaught promise rejection. You can solve this problem a couple different ways. 


Use the second callback parameter of the .then method.

con.execute('SELECT * FROM BTO_MDS.AlARMS', {}, { maxRows: 22000 })
    .then(result =&gt; {
        con.release();
        res.json({data: result.rows});
    }, ex =&gt; {
        con.release();
        res.status(500).json({message: ex.message});
    })

Use async / await and take advantage of the finally in try..catch..finally chain. This solution also has the benefit of avoiding the duplicate code sending error messages. I like this solution the best, but it would probably be even better to have an execute method on your Database class that handles releasing the connection for you.

export let getTest = async (req: Request, res: Response, next: NextFunction) =&gt; {
    const db = new Database();

    try {
        const con = await db.getConnection();
        try {
            const result = await con.execute('SELECT * FROM BTO_MDS.AlARMS', {}, { maxRows: 22000 });
            res.json({ data: result.rows });
        } finally {
            con.release();
        }
    } catch (ex) {
        res.status(500).json({ message: ex.message });
    }
};

For the future: Promise.prototype.finally is coming, currently a stage 3 proposal. Proposal. I wouldn't use this just yet.

db.getConnection()
    .then(con =&gt; {
        return con.execute('SELECT * FROM BTO_MDS.AlARMS', {}, { maxRows: 22000 })
            .then(result =&gt; {
                res.json({ data: result.rows });
            })
            .finally(() =&gt; {
                con.release();
            })
    })
    .catch(ex =&gt; {
        res.status(500).json({ message: ex.message });
    });



The trick to using promises effectively is to return them whenever possible. The original function can be somewhat simplified by re-throwing the error and returning the connection promise. This doesn't help a ton but it does remove the duplicate res.status(500) line, making it easier to change in the future if necessary. 

db.getConnection()
    .then(con =&gt; {
        return con.execute('SELECT * FROM BTO_MDS.AlARMS', {}, { maxRows: 22000 })
            .then(result =&gt; {
                con.release();
                res.json({ data: result.rows });
            }, ex =&gt; {
                con.release();
                throw ex;
            })
    })
    .catch(ex =&gt; {
        res.status(500).json({ message: ex.message });
    });