(قد تكون هذه نسخة مكررة من رقم 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)
لا أعتقد أنه يجب عليك إرجاع Promise.all([first, second]);
، لأنك قمت بالفعل بربط second
إلى first
. هل يمكنك من فضلك محاولة return first
؟ نظرًا لأن createTable
الثاني الخاص بك هو داخل then
وهو مقيد بالسلاسل من first
، فلا داعي لإضافته إلى Promise.all
، حيث سيتم تنفيذه على أي حال بينما يتم حل first
.
تنص مواصفات الوعد على أنه بمجرد الوفاء بالوعد ، لا ينبغي الوفاء به مرة أخرى ، ويجب أن تعيد جميع الاستدعاءات المستقبلية لـ then
النتيجة المخزنة مؤقتًا. إذا تم استيفاء كل من first
و second
، فإن Promise.all([first, second])
يجب أن يكون ~ no-op.
return first
له نفس السلوك - على سبيل المثال ، يحاول إنشاء الجداول first
و first
و second
، وهو _ حتى أكثر خطأ_ ، كما يجب لن يكون أبدًا أي رمز يقوم فعليًا بتقييم أي شيء داخل الوظيفة التي تم تمريرها إلى first.then
في هذا السيناريو.
حسنًا ، هذا يبدو غريبًا. عدم استخدام Promise.all
قد يعطي دفعة صغيرة في الأداء بالرغم من ذلك ؛)
لكن نعم ، يبدو أن هذا خطأ. سأضع علامة على هذا باعتباره خطأ في الوقت الحالي وانتظر حتى
هاها ، أنا لا أهتم بشكل خاص بقيمة أداء علامة واحدة في هجراتي: p
عذرًا ، لقد قدمت بيانًا خاطئًا أعلاه - لا يزال يتعين على return first
إنشاء الجدول الثاني ، إنها فقط أن نتيجة استدعاء .then
على نتيجة الوظيفة لن تنتظرها. والتي ، مع ذلك - يجب أن لا تعمل بالتأكيد first
، first
، second
!
لست متأكدًا من أنني أفهم تمامًا: لماذا لا ينتظر الجدول الثاني إنشاء الأول؟ نظرًا لأنك تتسلل من الوعد الأول باستخدام then
، فسيتم تنفيذها بشكل فعال في سلسلة. هذا لا ينبغي أن يكون مشكلة.
سيتم إنشاء الجدول الثاني ، نعم ، لكن نتيجة الدالة exports.up
لن تفعل ذلك. أي ، إذا اتصلت بـ exports.up().then
، فهذا يماثل استدعاء first.then
وليس second.then
- لأنه _is_ first.then
!
آه ، أساءت فهمك هناك - نعم أنت محق في ذلك!
لذا فإن الالتباس هنا هو أن طريقة createTable
لا تُرجع وعدًا ، ولكنها تُرجع عنصر SchemaBuilder
، وهو "قابل للتكلفة" ، أي استدعاء .then
على سيعيد الكائن وعدًا صالحًا A + ، لكن الشيء نفسه ليس وعدًا.
تم إجراء ذلك على وجه التحديد للسماح لك باستخدام بناء الجملة:
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
نعم ، لدينا رسوم بيانية تبعية أكثر تعقيدًا من ذلك ؛ كانت هذه مجرد حالة اختبار بسيطة! شكرا للمساعدة.
تضمين التغريدة
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
لا تُرجع وعدًا ، ولكنها تُرجع عنصرSchemaBuilder
، وهو "قابل للتكلفة" ، أي استدعاء.then
على سيعيد الكائن وعدًا صالحًا A + ، لكن الشيء نفسه ليس وعدًا.تم إجراء ذلك على وجه التحديد للسماح لك باستخدام بناء الجملة:
والتي يجب تشغيل عمليات الترحيل كما هو متوقع على نفس الاتصال بالتسلسل.
أيضًا ، ليست هناك حاجة إلى
Promise.all
هنا ، لأن هذا سيحقق نفس الشيء:على الرغم من أنك إذا أردت ، يمكنك القيام بما يلي:
وستعمل الأشياء على النحو المحدد في المواصفات.