(Ini mungkin duplikat dari # 312)
File migrasi seperti ini:
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) {
};
memberikan hasil sebagai berikut:
{ __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)
Saya tidak berpikir Anda harus mengembalikan Promise.all([first, second]);
, karena Anda telah merantai second
menjadi first
. Bisakah Anda mencoba hanya return first
? Karena createTable
ada di dalam then
yang dirantai dari first
, tidak perlu menambahkannya ke Promise.all
, karena akan dieksekusi bagaimanapun sementara first
sedang diselesaikan.
Spesifikasi promise mengatakan bahwa setelah promise terpenuhi, ia tidak akan pernah terpenuhi lagi, dan semua pemanggilan then
akan mengembalikan hasil yang disimpan dalam cache. Jika first
dan second
keduanya terpenuhi, maka Promise.all([first, second])
harus ~ tanpa operasi.
return first
memiliki perilaku yang sama - yaitu, mencoba membuat tabel first
, first
, dan second
, yang _bahkan lebih salah_, sebagaimana mestinya tidak pernah ada kode yang benar-benar mengevaluasi apa pun di dalam fungsi yang diteruskan ke first.then
dalam skenario itu.
Uhm ok kedengarannya aneh. Tidak menggunakan Promise.all
dapat memberikan sedikit dorongan dalam kinerja;)
Tapi ya, ini sepertinya salah. Saya akan menandai ini sebagai bug untuk saat ini dan menunggu sampai @tgriesser ikut serta . Terima kasih telah melaporkan!
Haha, saya tidak terlalu peduli dengan kinerja satu tick dalam migrasi saya: p
Maaf, saya membuat pernyataan yang salah di atas - return first
harus tetap membuat tabel kedua, hanya saja hasil pemanggilan .then
pada hasil fungsi tidak akan menunggu. Yang mana, w / e - seharusnya tetap tidak menghasilkan first
, first
, second
!
Tidak yakin saya sepenuhnya mengerti: Mengapa tabel ke-2 tidak menunggu untuk pembuatan yang pertama? Karena Anda memutuskan janji pertama menggunakan then
janji tersebut akan dijalankan secara seri. Itu seharusnya tidak menjadi masalah.
Pembuatan tabel kedua akan, ya, tetapi hasil dari fungsi exports.up
tidak. Yaitu, jika Anda memanggil exports.up().then
, itu sama dengan memanggil first.then
dan bukan second.then
- karena _is_ first.then
!
Ah, salah paham di sana - ya, Anda benar tentang itu!
Jadi kebingungan di sini adalah bahwa metode createTable
tidak mengembalikan sebuah janji, melainkan mengembalikan objek SchemaBuilder
, yang merupakan "thenable", yaitu memanggil .then
pada objek akan mengembalikan janji A + yang valid, tetapi objek itu sendiri bukan janji.
Ini dilakukan secara khusus untuk memungkinkan Anda menggunakan sintaks:
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
});
yang harus menjalankan migrasi seperti yang diharapkan pada koneksi yang sama secara berurutan.
Juga, tidak perlu Promise.all
sini, karena ini akan menghasilkan hal yang sama:
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');
});
});
};
meskipun jika Anda mau, Anda dapat melakukan:
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]);
};
dan semuanya akan bekerja seperti yang ditentukan oleh spesifikasi.
Ok itu menjelaskan itu. Tidak tahu itu - maaf atas kebingungannya karena tidak bisa langsung memberikan jawaban langsung @SohumB
Ya, kami memiliki grafik ketergantungan yang lebih rumit dari itu; ini hanya kasus uji minimal! Terima kasih untuk bantuannya.
@bayu_joo
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!
Komentar yang paling membantu
Jadi kebingungan di sini adalah bahwa metode
createTable
tidak mengembalikan sebuah janji, melainkan mengembalikan objekSchemaBuilder
, yang merupakan "thenable", yaitu memanggil.then
pada objek akan mengembalikan janji A + yang valid, tetapi objek itu sendiri bukan janji.Ini dilakukan secara khusus untuk memungkinkan Anda menggunakan sintaks:
yang harus menjalankan migrasi seperti yang diharapkan pada koneksi yang sama secara berurutan.
Juga, tidak perlu
Promise.all
sini, karena ini akan menghasilkan hal yang sama:meskipun jika Anda mau, Anda dapat melakukan:
dan semuanya akan bekerja seperti yang ditentukan oleh spesifikasi.