web-dev-qa-db-ja.com

node-postgresでのAsync / Awaitの使用

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秒後にクラッシュし、このエラーを適切に処理していません

誰かが私がここで欠けているものを指摘できますか?

3
Richlewis

async関数またはPromiseがキャッチされないエラーをスローした場合、またはキャッチャーもスローした場合(

throw error;

これは、関数のcallerが、処理するために拒否された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に大きなメリットをもたらすことなく、多くの構文ノイズを追加します。代わりにプレーンなPromiseの使用を検討するかもしれません:

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は、コードでよりフラットに見せたい.thenがいくつかある場合に光ります。 .thenが1つしかない場合、IMOをasync/await構文に変換してもあまりメリットはありません。もちろん、それはあなた次第です。

10