(これは#312の複製である可能性があります)
次のような移行ファイル:
exports.up = function(knex, Promise) {
var first = knex.schema.createTable('first', function(table) {
table.increments('id');
table.string('name');
});
var second = first.then(function() {
return knex.schema.createTable('second', function(table) {
table.increments('id');
table.string('name');
});
});
return Promise.all([first, second]);
};
exports.down = function(knex, Promise) {
};
次の出力が得られます。
{ __cid: '__cid1',
sql: 'create table "first" ("id" serial primary key, "name" varchar(255))',
bindings: [] }
{ __cid: '__cid2',
sql: 'create table "first" ("id" serial primary key, "name" varchar(255))',
bindings: [] }
{ __cid: '__cid3',
sql: 'create table "second" ("id" serial primary key, "name" varchar(255))',
bindings: [] }
error: duplicate key value violates unique constraint "pg_type_typname_nsp_index"
at Connection.parseE (/home/sohum/node_modules/pg/lib/connection.js:526:11)
at Connection.parseMessage (/home/sohum/node_modules/pg/lib/connection.js:356:17)
at Socket.<anonymous> (/home/sohum/node_modules/pg/lib/connection.js:105:22)
at Socket.EventEmitter.emit (events.js:95:17)
at Socket.<anonymous> (_stream_readable.js:745:14)
at Socket.EventEmitter.emit (events.js:92:17)
at emitReadable_ (_stream_readable.js:407:10)
at emitReadable (_stream_readable.js:403:5)
at readableAddChunk (_stream_readable.js:165:9)
at Socket.Readable.push (_stream_readable.js:127:10)
すでにsecond
をfirst
チェーンしているので、 Promise.all([first, second]);
を返す必要はないと思います。 return first
だけやってみてください。 2番目のcreateTable
はfirst
からチェーンされたthen
あるため、実行されるため、 Promise.all
に追加する必要はありません。とにかくfirst
が解決されている間。
promiseの仕様では、promiseが実行されると、それは二度と実行されるべきではなく、 then
を今後呼び出すと、キャッシュされた結果が返されるはずです。 first
とsecond
両方が満たされている場合、 Promise.all([first, second])
は〜何もしないはずです。
return first
動作は同じです。つまり、 first
、 first
、およびsecond
テーブルを作成しようとしますが、これは_さらに間違っています_。そのシナリオでfirst.then
に渡された関数内の何かを実際に評価するコードであってはなりません。
うーん、それは奇妙に聞こえます。 Promise.all
を使用しないと、パフォーマンスが少し向上する可能性があります;)
しかし、ええ、これは間違っているようです。 今のところこれをバグとしてマークし、 @ tgriesserがチャイムを
ハハ、私は移行で1ティック相当のパフォーマンスを特に気にしません:p
申し訳ありませんが、上記で間違ったステートメントを作成しました- return first
はまだ2番目のテーブルを作成するはずです、それは関数の結果で.then
を呼び出した結果がそれを待たないということだけです。 これは、w / e-それでも間違いなくfirst
、 first
、 second
実行しないはずです!
完全に理解しているかどうかわからない:2番目のテーブルが最初のテーブルの作成を待たないのはなぜですか? then
を使用して最初の約束を連鎖させるので、それらは効果的に直列に実行されます。 それは問題ではないはずです。
2番目のテーブルの作成は可能ですが、 exports.up
関数の結果はそうではありません。 あなたが呼び出す場合すなわち、 exports.up().then
、それが呼び出すのと同じですfirst.then
及びませんsecond.then
それは_is_ので- first.then
!
ああ、そこであなたを誤解しました-ええ、あなたはそれについて正しいです!
したがって、ここでの混乱は、 createTable
メソッドがpromiseを返さず、むしろ「thenable」であるSchemaBuilder
オブジェクトを返すことです。つまり、 .then
を呼び出します。オブジェクトは有効なA + promiseを返しますが、オブジェクト自体はpromiseではありません。
これは、構文を使用できるようにするために特別に行われました。
return knex.schema.createTable('first', function(table) {
table.increments('id');
table.string('name');
})
.createTable('second', function(table) {
table.increments('id');
table.string('name');
}).then(function() {
// all done
});
これは、同じ接続で期待どおりに移行を順番に実行する必要があります。
また、ここではPromise.all
は必要ありません。これにより、同じことが達成されます。
exports.up = function(knex, Promise) {
return knex.schema.createTable('first', function(table) {
table.increments('id');
table.string('name');
}).then(function() {
return knex.schema.createTable('second', function(table) {
table.increments('id');
table.string('name');
});
});
};
ただし、必要に応じて、次のことができます。
exports.up = function(knex, Promise) {
var first = knex.schema.createTable('first', function(table) {
table.increments('id');
table.string('name');
}).then(); // coerce thenable to a promise
var second = first.then(function() {
return knex.schema.createTable('second', function(table) {
table.increments('id');
table.string('name');
});
});
return Promise.all([first, second]);
};
そして物事は仕様で定義されているように機能します。
それはそれを説明します。 知らなかった-すぐに正解できないことで混乱してすみません@SohumB
ええ、それよりも複雑な依存関係グラフがあります。 これは最小限のテストケースでした! 助けてくれてありがとう。
@johanneslumpe
sohum<strong i="8">@diurnal</strong> ~ % cat test.js
var Promise = require('bluebird');
function promises() {
var first = Promise.resolve('wee');
var second = first.then(function() {
console.log('delayin');
return Promise.delay(1000);
}).then(function() {
console.log('done!');
});
return first;
}
promises().then(function() { console.log('yep, first is finished'); });
sohum<strong i="9">@diurnal</strong> ~ % node test.js
delayin
yep, first is finished
done!
最も参考になるコメント
したがって、ここでの混乱は、
createTable
メソッドがpromiseを返さず、むしろ「thenable」であるSchemaBuilder
オブジェクトを返すことです。つまり、.then
を呼び出します。オブジェクトは有効なA + promiseを返しますが、オブジェクト自体はpromiseではありません。これは、構文を使用できるようにするために特別に行われました。
これは、同じ接続で期待どおりに移行を順番に実行する必要があります。
また、ここでは
Promise.all
は必要ありません。これにより、同じことが達成されます。ただし、必要に応じて、次のことができます。
そして物事は仕様で定義されているように機能します。