node / pg / PSQL: создание таблиц с помощью обещаний - PullRequest
0 голосов
/ 01 июля 2019

Я пишу простое приложение Node / Express / React / Postgres и использую пакет pg для взаимодействия с моим сервером Postgres.

Мне требуются три таблицы: table1, table2 и table3. table2 имеет внешний ключ в table1, а table3 имеет внешний ключ в table 2, поэтому порядок создания таблиц в следующем порядке: table1, затем table2, затем table3.

Я пытаюсь использовать обещания для обеспечения этого порядка в моих вызовах создания асинхронных таблиц. Обычно я следовал предложенной Брайаном Карлсоном структуре проекта 1017 *, но, очевидно, я делаю что-то не так.

Вот упрощенные, соответствующие файлы из моего проекта:

db.js:

const { Pool } = require('pg');

// Create pool connection to database
const pool = new Pool({
  user: XXXX,
  host: XXXX,
  database: XXXX,
  password: XXXX,
  port: XXXX
});

// Pool emitters
pool.on('connect', () => {
  console.log('Connected a client to the database');
});

pool.on('remove', () => {
  console.log('Disconnected a client from the database');
});

pool.on('error', (err, client) => {
  console.error('Unexpected error on idle client', err);
  process.exit(-1);
});

// This structure taken from Brian Carlson's pg API Documentation
// https://node-postgres.com/guides/project-structure
module.exports = {
  query: (text, params) => {
    console.log('Making a query!');
    return pool.query(text, params);
  }
};

table_scripts.js:

const db = require('../db');

const Database_Scripts = {
  create_table_1: () => {
    const create_table_1_query = {
      text: `CREATE TABLE IF NOT EXISTS
        public.table_1
      (
        id smallserial,
        name text NOT NULL,
        PRIMARY KEY (id)
      );`
    };
    return db.query(create_table_1_query);
  },

  create_table_2: () => {
    const create_table_2_query = {
      text: `CREATE TABLE IF NOT EXISTS
      public.table_2
    (
        id smallserial,
        table_1_id integer NOT NULL REFERENCES public.table_1(id),
        name text NOT NULL,
        PRIMARY KEY (id)
    );`
    };
    return db.query(create_table_2_query);
  },

  create_projects_table: () => {
    const create_table_3_query = {
      text: `
      CREATE TABLE IF NOT EXISTS
          public.table_3
          (
           id smallserial,
           table_3_id integer NOT NULL REFERENCES public.table_2(id),
           name text NOT NULL,
           PRIMARY KEY (id)
          );`
    };

    return db.query(create_table_3_query);
  }
};

module.exports = Database_Scripts;

create_tables.js:

const Table_Scripts = require('./table_scripts');

Table_Scripts.create_table_1()
  .then(Table_Scripts.create_table_2())
  .then(Table_Scripts.create_table_3())
  .catch(error => console.log(error.stack));

package.json:

{
  "name": "app",
  "version": "0.0.0",
  "scripts": {
    "start": "nodemon ./bin/www",
    "create_tables": "node ./database/scripts/create_tables.js"
  }
}

Когда я запускаю сценарий create_tables (npm run-script create_tables), я получаю следующие (очищенные) ошибки:

Connected a client to the database
Connected a client to the database
Connected a client to the database
Disconnected a client from the database
(node:13444) UnhandledPromiseRejectionWarning: error: relation "public.table_1" does not exist
(node:13444) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a
catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:13444) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Disconnected a client from the database
(node:13444) UnhandledPromiseRejectionWarning: error: relation "public.table_2" does not exist
(node:13444) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a
catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
Disconnected a client from the database

Мне удалось заставить этот скрипт работать, преобразовывая функции в асинхронные функции, однако мне бы очень хотелось понять, что я здесь делаю неправильно.

1 Ответ

0 голосов
/ 02 июля 2019

Похоже, ваша проблема в том, что вы одновременно создаете таблицы, несмотря на явную необходимость сделать обратное.

Согласно документации , pool.query() возвращает обещание, если не предоставлена ​​функция обратного вызова в качестве третьего аргумента. Вам нужно дождаться выполнения каждого из ваших db.query() обещаний. Таким образом, он будет ждать создания первой таблицы, затем создаст вторую и, наконец, третью.

Я бы рекомендовал использовать синтаксис async / await

async function createTables () {
    try {
        const create_table_1_query = {
            text: `yourQuery1`
        };
        // awaits for the first table to be created
        await db.query(create_table_1_query);

        const create_table_2_query = {
            text: `yourQuery2`
        };
        // awaits for the second table to be created
        await db.query(create_table_2_query);

        const create_table_3_query = {
            text: `yourQuery3`
        };
        // awaits for the third table to be created
        await db.query(create_table_3_query);
    } catch (e) {
        console.error(e.stack);
    }
}

module.exports.createTables = createTables;

Затем вы можете позвонить await createTables();

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...