简体   繁体   中英

Knex MySQL Migration “Unhandled rejection Error: Transaction query already complete”

I'm new to pretty much everything. I tried using a single migration file to create all the tables in a MySQL database (20 tables).

exports.up = function(knex, Promise) {

function createTable1() {
    return knex.schema.createTableIfNotExists('Table1', (t) => {
      t.increments('id').primary();
      t.string('col_1', 48).unique().notNullable();
      t.timestamps(true, true);
    }).catch((e) => console.log(e));
}

function createTable2() {
    return knex.schema.createTableIfNotExists('Table2', (t) => {
      t.increments('id').primary();
      t.string('col_1', 48).unique().notNullable();
      t.integer('someId').unsigned().references('Table1.id')
      t.timestamps(true, true);
    }).catch((e) => console.log(e));
}

function createTable3() {
    return knex.schema.createTableIfNotExists('Table3', (t) => {
      t.increments('id').primary();
      t.string('col_1', 48).unique().notNullable();
      t.integer('someId').unsigned().references('Table1.id')
      t.integer('someOtherId').unsigned().references('Table2.id')
      t.timestamps(true, true);
    }).catch((e) => console.log(e));
}
... //similar functions for all 20 tables

return Promise.all([
    createTable1()
    .then(createTable2())
    .then(createTable3())
    ...
    .then(createTable20())
    .catch((e) => console.log(e.sql))
  ]);
}

exports.down = function(knex, Promise) {

  return knex.schema.dropTable('Table1')
  .then(knex.schema.dropTable('Table2'))
  .then(knex.schema.dropTable('Table3'))
  ...
  .then(knex.schema.dropTable('Table20'))
  .catch((e) => console.log(e.sql))
};

I expected knex to execute all of the sql queries in one transaction

The migration executes but generates the following error:

Unhandled rejection Error: Transaction query already complete, run with DEBUG=knex:tx for more info

Admittedly I don't have a firm grasp with how to use promises correctly and I understand that the return Promise.all block will not necessarily generate & execute the SQL queries in that same order, but should I even be doing this? Does it make more sense to create a separate migration file for each table?

You are invoking functions in your promise chain instead of chaining them. The first function should be executed and then chained with other functions in the .then . You also seem to be mixing up promise chaining and the usage of Promise.all .

If you want each table to be created sequentially drop the Promise.all and the function calls:

return createTable1()
  .then(createTable2)
  .then(createTable3)
  ...
  .then(createTable20)
  .catch((e) => console.log(e.sql))

If you want to create N tables all at the same time use Promise.all like this:

return Promise.all([createTable1(), createTable2(), ..., createTable20()])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM