هل جافا سكريبت مفردة الخيوط؟إذا لم يكن الأمر كذلك، كيف يمكنني الحصول على الوصول المتزامن إلى البيانات المشتركة؟

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

سؤال

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

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

تم التعديل للإضافة:

  • المكتبة المعنية هي SIMILE الجدول الزمني ومكتبة اياكس الخاصة بها؛
  • معالج الحدث يستدعي SimileAjax.DOM.cancelEvent(domEvt), والذي أفترض بناءً على الاسم أنه يلغي فقاعات الأحداث؛
  • فقط لجعل الأمور أكثر تعقيدًا، ما أفعله بالفعل هو بدء مهلة إذا لم يتم إلغاؤها بواسطة أ moustout يعرض النافذة المنبثقة، ويهدف هذا إلى منع وميض النوافذ المنبثقة بشكل مزعج ولكن يكون لها تأثير عكسي بشكل مزعج.

سأقوم بكزة أخرى وأرى ما إذا كان بإمكاني معرفة أين أخطأت.:-)

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

المحلول

نعم، جافا سكريبت هي خيط واحد.حتى مع المتصفحات مثل Google Chrome، يوجد موضوع واحد لكل علامة تبويب.

بدون معرفة كيف تحاول إلغاء نافذة منبثقة من أخرى، من الصعب تحديد سبب مشكلتك.

إذا كانت وحدات DIV الخاصة بك متداخلة مع بعضها البعض، فقد يكون لديك انتشار الحدث مشكلة.

نصائح أخرى

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

أستخدم ExtJS ويقومون بعمل تلميحات الأدوات ومربعات الرسائل كعناصر وزن الذبابة.آمل أن تكون أطرك تحتوي على عناصر وزن الذبابة أيضًا، وإلا فسيتعين عليك فقط إنشاء مفردة خاصة بك وتسميتها.

إنه مترابطة واحدة في المتصفحات.تعمل معالجات الأحداث بشكل غير متزامن في مؤشر ترابط واحد، ولا يعني عدم الحظر دائمًا وجود مؤشرات ترابط متعددة.هل أحد div الخاص بك هو طفل للآخر؟لأن الأحداث تنتشر مثل الفقاعات في شجرة الدوم من الطفل إلى الوالدين.

على غرار ما قاله pkaeding، من الصعب تخمين المشكلة دون رؤية الترميز والنص الخاص بك؛ومع ذلك، أجرؤ على القول إنك لا توقف نشر الحدث بشكل صحيح و/أو أنك لا تخفي العنصر الموجود بشكل صحيح.لا أعرف إذا كنت تستخدم إطار عمل أم لا، ولكن إليك حلًا ممكنًا باستخدام النموذج الأولي:

// maintain a reference to the active div bubble
this.oActiveDivBubble = null;

// event handler for the first div
$('exampleDiv1').observe('mouseover', function(evt) {
    evt.stop();
    if(this.oActiveDivBubble ) {
        this.oActiveDivBubble .hide();
    }
    this.oActiveDivBubble = $('exampleDiv1Bubble');
    this.oActiveDivBubble .show();

}.bind(this));

// event handler for the second div
$('exampleDiv2').observe('mouseover'), function(evt) {
    evt.stop();
    if(this.oActiveDivBubble) {
        this.oActiveDivBubble.hide();
    }
    this.oActiveDivBubble = $('exampleDiv2Bubble');
    this.oActiveDivBubble .show();
}.bind(this));

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

وفي كلتا الحالتين، نأمل أن يساعد هذا.

لعِلمِكَ:اعتبارًا من Firefox 3، هناك تغيير ذو صلة إلى حد كبير بهذه المناقشة:تؤدي سلاسل التنفيذ إلى فصل طلبات XMLHttpRequest المتزامنة (ولهذا السبب لا تتجمد الواجهة هناك أثناء الطلبات المتزامنة) ويستمر التنفيذ.عند اكتمال الطلب المتزامن، يستمر مؤشر الترابط الخاص به أيضًا.لن يتم تنفيذها في نفس الوقت، ولكن الاعتماد على افتراض توقف مؤشر ترابط واحد أثناء حدوث إجراء متزامن (طلب) لم يعد قابلاً للتطبيق بعد الآن.

من الممكن أن الشاشة لا يتم تحديثها بالسرعة الكافية.اعتمادًا على مكتبة JS التي تستخدمها، قد تتمكن من تأخير تأثير "العرض" المنبثق قليلاً.

وهنا نسخة العمل، أكثر أو أقل.عند إنشاء العناصر نعلق أ mouseover حدث:

var self = this;
SimileAjax.DOM.registerEvent(labelElmtData.elmt, "mouseover", function (elt, domEvt, target) {
    return self._onHover(labelElmtData.elmt, domEvt, evt);
});

يؤدي هذا إلى استدعاء دالة تحدد المهلة (يتم إلغاء المهلات الموجودة مسبقًا لعنصر مختلف أولاً):

MyPlan.EventPainter.prototype._onHover = function(target, domEvt, evt) {            
    ... calculate x and y ...
    domEvt.cancelBubble = true;
    SimileAjax.DOM.cancelEvent(domEvt);
    this._futureShowBubble(x, y, evt);

    return false;
}
MyPlan.EventPainter.prototype._futureShowBubble = function (x, y, evt) {
    if (this._futurePopup) {
        if (evt.getID() == this._futurePopup.evt.getID()) {
            return;
        } else {
            /* We had queued a different event's pop-up; this must now be cancelled. */
            window.clearTimeout(this._futurePopup.timeoutID);
        } 
    }
    this._futurePopup = {
        x: x,
        y: y,
        evt: evt
    };    
    var self = this;
    this._futurePopup.timeoutID =  window.setTimeout(function () {
            self._onTimeout();
    }, this._popupTimeout);
}

وهذا بدوره يُظهر الفقاعة إذا انطلقت قبل أن يتم إلغاؤها:

MyPlan.EventPainter.prototype._onTimeout = function () {
    this._showBubble(this._futurePopup.x, this._futurePopup.y, this._futurePopup.evt);

};

MyPlan.EventPainter.prototype._showBubble = function(x, y, evt) {
    if (this._futurePopup) {
        window.clearTimeout(this._futurePopup.timeoutID);
        this._futurePopup = null;
    }        
    ...

    SimileAjax.WindowManager.cancelPopups();
    SimileAjax.Graphics.createBubbleForContentAndPoint(...);
};

يبدو أن هذا يعمل الآن، فقد قمت بتعيين المهلة على 200 مللي ثانية بدلاً من 100 مللي ثانية.لست متأكدًا من سبب حدوث مهلة قصيرة جدًا لحدوث الفقاعات المتعددة، ولكن أعتقد أن انتظار أحداث النوافذ أو قد يستمر حدوث شيء ما أثناء وضع العناصر المضافة حديثًا.

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