Knex: الوعود لا تتصرف كما هو متوقع في الهجرات

تم إنشاؤها على ١٦ يونيو ٢٠١٤  ·  10تعليقات  ·  مصدر: knex/knex

(قد تكون هذه نسخة مكررة من رقم 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)
question

التعليق الأكثر فائدة

لذا فإن الالتباس هنا هو أن طريقة 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]);
};

وستعمل الأشياء على النحو المحدد في المواصفات.

ال 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!
هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

arconus picture arconus  ·  3تعليقات

marianomerlo picture marianomerlo  ·  3تعليقات

ghost picture ghost  ·  3تعليقات

saurabhghewari picture saurabhghewari  ·  3تعليقات

legomind picture legomind  ·  3تعليقات