مسج، الحوار، علامات التبويب وجداول البيانات:كيف تنتظر حتى ينتهي أحد قبل المضي قدمًا؟

StackOverflow https://stackoverflow.com//questions/21011218

سؤال

لدي مشكلة صعبة، والتي يمكن حلها من خلال عمليات الاسترجاعات المتسلسلة، ولكن هذا يؤدي إلى تعليمات برمجية معقدة للغاية.

لدي بعض المكونات المتداخلة:مربع حوار jQueryUI.بداخله، لدي علامات تبويب jQueryUI.وفي كل علامة تبويب، لدي مكون DataTables، يستدعي بيانات AJAX.

مشكلتي هي أنه عندما أقوم بتحميل كل HTML داخل مربع الحوار، يتم تشغيل كل شيء بالتوازي:تحاول علامات التبويب إنشاء نفسها، بينما يقوم كل DataTable بجمع بياناته، كل ذلك في نفس الوقت!

والنتيجة فوضى كاملة:لا تحتوي علامات التبويب على العناصر الصحيحة، نظرًا لأن كل DataTable ينشئ عقدًا جديدة على DOM، بعد تهيئة علامات التبويب.يفترض مربع الحوار أبعادًا خاطئة، لأن DOM كان صغيرًا عند تهيئته، ولكنه كبرت عندما عرض كل DataTable البيانات.

لجعل الأمور تعمل، سأحتاج إلى:

1) Wait for each DataTable to initialize.
2) When they're all done, initialize the Tabs.
3) When Tabs are ready, finally open the Dialog.

هل هناك طريقة سهلة لعمل ذلك؟؟أستخدم حاليًا الكثير من عمليات الاسترجاعات، وكل المحتوى ديناميكي، ومدفوع بقاعدة البيانات، لذلك يتعين علي القيام بالكثير من التعميم، ولا يمكن ترميز أي شيء تقريبًا.الشيء يعمل بالفعل، لكنه قبيح!

هذه إحدى المواقف التي أقوم فيها بإيقاف تشغيل سلوك JavaScript غير المتزامن وجعله متزامنًا ومتسلسلاً، إذا استطعت.

ربما يمكن لقائمة انتظار jQuery أو الوعد أو شيء من هذا القبيل أن يساعدني؟أي مساعدة سوف تكون محل تقدير كبير!

هل كانت مفيدة؟

المحلول

لقد وجدت الحل المناسب، لذا سأنشره هنا لمساعدة أي شخص آخر يواجه مشكلة مماثلة.

أولاً، وجدت أن DataTables بها حدث تم إطلاقه عند الإنشاء.إنه الحدث "init":

$("#TableID").on("init", function() { whatever(); } );

ثانيًا، مشكلتي الأخرى هي العدد غير المحدد من DataTables الذي كان علي انتظاره قبل تهيئة علامات التبويب.لذلك قمت بإنشاء وظيفة صغيرة، تسمى RenderManager، لتتبع جميع جداول البيانات الخاصة بي.عند انتهاء الأخير، يتم استدعاء رد الاتصال.لقد جعلت هذه الوظيفة عامة جدًا، بحيث يمكن استخدامها في أي موقف يتعين عليك فيه الانتظار حتى تنتهي عدة عمليات معالجة متوازية قبل المضي قدمًا:

function RenderManager(action, id, callback) 
{
  if(typeof RenderManager.groups == 'undefined' ) RenderManager.groups = {};

  switch(action)
  {
    case "init":
      RenderManager.groups[id] = { _callback:callback, _counter:0 };
    break;
    case "add":
      if(typeof RenderManager.groups[id] == 'undefined' ) 
        console.log('Group "'+id+'" referenced before init.');
      else 
        RenderManager.groups[id]._counter++;
    break;
    case "remove":
      if(typeof RenderManager.groups[id] == 'undefined' ) 
        console.log('Group "'+id+'" referenced before init.');
      else
      {
        RenderManager.groups[id]._counter--;
        if(RenderManager.groups[id]._counter == 0) 
          RenderManager.groups[id]._callback();
      }
    break;
  }
}

الاستخدام بسيط:أولاً، اتصل بها باستخدام init، لإعلام اسم المجموعة ورد الاتصال المطلوب:

RenderManager('init', 'MyGroup', function() { CreateTabs(); });

لكل DataTable تم إنشاؤه (أو بدأت عملية متوازية)، قم بإضافته إلى المجموعة:

RenderManager('add', 'MyGroup');

ومن ثم ربط أ remove لكل DataTable init الحدث (أو حتى نهاية أي عملية موازية)، باستخدام:

$("#TableID").on("init", function() { RenderManager('remove', 'MyGroup'); } );

هذا كل شيء!عندما ينتهي DataTable الأخير من مهمته، CreateTabs(); سيتم استدعاؤه، بغض النظر عن ترتيب التنفيذ، بغض النظر عن DataTable الذي انتهى أولاً.

كما ترون، هذه الوظيفة هي مجرد عداد:عندما يعود "المكدس" إلى الصفر، يتم تشغيل رد الاتصال.يمكن تحسينه من خلال تسجيل معرفات كل عنصر، ولكن هذا يعد مبالغة في حل المشكلة التي أقوم بحلها حاليًا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top