Node.js通用连接池:资源获取后异常场景下的资源释放问询
Hey folks, let's break down how to handle that tricky scenario with node-pool where an error crops up after you've grabbed a resource but before you've had a chance to release it.
First, let's recap the standard resource flow you shared:
const resourcePromise = myPool.acquire(); resourcePromise .then(function(client) { client.query("select * from foo", [], function() { // Return object to the pool myPool.release(client); }); }) .catch(function(err) { // Handle errors });
The big issue here is: if an exception happens inside the client.query callback (or anywhere between acquiring the client and calling release), that client will never get sent back to the pool. Over time, this causes resource leaks—your pool will run out of available connections, leading to timeouts and failed requests.
The Solution: Use try/finally or Promise finally
The safest way to guarantee resources are always released, no matter what errors occur, is to use a cleanup mechanism that runs regardless of success or failure. Here are two solid approaches:
Option 1: Async/Await with try/finally (cleanest syntax)
Async/await makes this pattern straightforward to read and maintain:
async function usePoolConnection() { let client; try { // Grab the resource from the pool client = await myPool.acquire(); // Run your query and process data here const queryResult = await client.query("select * from foo"); // Do any data processing you need—even if this throws, finally will run } catch (error) { // Handle any errors from acquiring the client or processing data console.error("Something went wrong:", error); } finally { // Always release the client back to the pool, if we successfully acquired it if (client) { myPool.release(client); } } } // Call the function to use the pool usePoolConnection();
Option 2: Promise Chain with finally
If you prefer sticking to the original promise-based syntax, add a finally block to your chain to ensure cleanup:
myPool.acquire() .then(function(client) { // Wrap your query and processing in a promise chain, then add finally return client.query("select * from foo") .then(function(result) { // Process your query result here }) .finally(function() { // No matter what happens, send the client back to the pool myPool.release(client); }); }) .catch(function(error) { // Handle errors from acquiring the client or the query process console.error("Error encountered:", error); });
For Callback-Based Query Methods
If your client.query uses callbacks instead of returning a promise, you can still ensure cleanup by wrapping the callback logic in a try/finally block:
myPool.acquire() .then(function(client) { client.query("select * from foo", [], function(err, result) { try { if (err) throw err; // Process your result here } catch (processingError) { console.error("Processing failed:", processingError); } finally { // Always release the client, even if processing failed myPool.release(client); } }); }) .catch(function(acquireError) { console.error("Failed to acquire client:", acquireError); });
Key Notes
- Never skip cleanup: Failing to release clients will drain your pool over time—this is one of the most common pitfalls with connection pools.
finallyis your friend: It ensures your cleanup code runs whether the operation succeeds, throws an error, or is rejected.- Always check if you actually acquired the client: If
acquire()fails,clientwill be undefined, so we add a check to avoid errors in thefinallyblock.
内容的提问来源于stack exchange,提问作者Nosairat

