将 Async/Await 与 node-postgres 一起使用

Posted

技术标签:

【中文标题】将 Async/Await 与 node-postgres 一起使用【英文标题】:Using Async/Await with node-postgres 【发布时间】:2019-05-23 11:07:46 【问题描述】:

我正在使用 node-postgres 查询我的数据库,想知道如何使用 async/await 并正确处理错误

我使用的一个例子是一个非常简单的查询

const  Pool  = require('pg');

let config;
if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'staging') 
  config =  connectionString: process.env.DATABASE_URL, ssl: true ;
 else 
  config = 
    host: 'localhost',
    user: 'myuser',
    database: 'mydatabase',
  ;


const pool = new Pool(config);

async function getAllUsers() 
  let response;
  try 
    response = await pool.query('select * FROM users');
   catch (error) 
    throw error;
  
  return response.rows;

然后在我的routes.js 我有

app.get('/all_users', async (req, res) => 
  const users = await queries.getAllUsers();
  console.log(users); // returns all users fine
);

这是我目前的理解,但我认为我没有正确处理这个问题,因为当涉及到错误时,我的应用程序将冻结并抛出 UnhandledPromiseRejectionWarning。因此,如果我提供了一个不正确的表格,例如

async function getAllUsers() 
  let response;
  try 
    response = await pool.query('select * FROM notable');
   catch (error) 
    throw error;
  
  return response.rows;


UnhandledPromiseRejectionWarning: error: relation "notable" does not exist

应用程序将在 30 秒后崩溃,我没有优雅地处理此错误

谁能指出我在这里遗漏了什么?

【问题讨论】:

对于处理错误,您可能需要查看 await-to-js,它为使用 Promise 时的错误处理提供更简洁的语法 【参考方案1】:

async 函数或Promise 抛出未捕获的错误,或者当捕获器也 抛出时,例如你的

throw error;

这意味着函数的调用者将面临一个被拒绝的Promise来处理。如果您在调用者中使用await,那么您还必须在调用者中使用try/catch 才能正确捕获错误:

app.get('/all_users', async (req, res) => 
  try 
    const users = await queries.getAllUsers();
    console.log(users);
   catch(e) 
    // handle errors
  
);

无需在消费者中使用try/catch 即可解决错误的另一种方法是不要throw catch 中的错误:

async function getAllUsers() 
  let response;
  try 
    response = await pool.query('select * FROM users');
    return response.rows;
   catch (error) 
    // handle error
    // do not throw anything
  

但这会使消费者更难知道何时出现错误。

在这种特殊情况下,async/await/try/catch 结构会增加很多语法噪音,但对 IMO 没有多大好处 - 目前,您可以考虑使用纯 Promises 代替:

const getAllUsers = () => pool.query('select * FROM users')
  .then(response => response.rows);

// and:
app.get('/all_users', (req, res) => 
  queries.getAllUsers()
    .then((users) => 
      console.log(users);
    )
    .catch((err) => 
      // handle errors
    );
);

asyncawait 当您希望在代码中看起来更扁平的几个 .thens 时会发光。如果只有一个.then,IMO 将其转换为async/await 语法并没有多大好处。当然,这取决于你。

【讨论】:

除了上述之外,一个常见的选择是使用服务器包或中间件自动捕获未经处理的错误并将它们转换为 HTTP 500。 感谢您的回答,也许我不必要地使用了 async/await,提出了有效的观点。还要感谢您澄清我应该从调用方处理错误(我错过了那里的简单事情) 通常有一个查询执行器函数,它具有 try catch 并在其他地方调用它,因此您不必在任何地方重复它。见node-postgres.com/guides/project-structure

以上是关于将 Async/Await 与 node-postgres 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

将 async/await 与 Dispatcher.BeginInvoke() 一起使用

将 fetch 与 async/await 一起使用会返回 [object Object]

将 Async/Await 与 node-postgres 一起使用

将 Async/await 与 mongoose 一起使用

将 async/await (Swift 5.5) 与 firebase 实时数据库一起使用

Async/Await 与 JQuery 文档 READY