Ist JavaScript single threaded? Wenn nicht, wie erhalte ich Zugriff auf gemeinsam genutzte Daten synchronisiert?

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

Frage

Ich habe eine Webseite mit DIVs mit einem mouseover-Handler, der eine Pop-up-Informationen Blase zeigen sollte. Ich will nicht mehr als ein Info-Blase zu einer Zeit sichtbar sein. Aber wenn der Benutzer die Maus schnell über zwei Elemente bewegt, bekomme ich manchmal zwei Blasen. Dies sollte nicht passieren, da der Code ein Popup-zum Anzeigen der vorherigen Pop-up aufhebt.

Wenn dies ein Multi-Threaded-System wurde dann wäre das Problem offensichtlich: Es gibt zwei Threads ein Pop-up zu zeigen versuchen, und sie beide stornieren Pop-ups dann ihre eigenen Pop-ups Pop-up. Aber ich angenommen JavaScript ist immer Single-Thread ausgeführt werden, was dies verhindern würde. Liege ich falsch? Ist ich brauche synchronisierter Zugriff auf gemeinsam genutzte Daten Event-Handler Fall, in dem asynchron ausgeführt wird, oder soll ich stattdessen für Fehler in der Code-Bibliothek suche zum Löschen von Pop-ups?

Edited hinzufügen:

  • Die Bibliothek in Frage SIMILE Timeline und seine Ajax-Bibliothek;
  • Der Event-Handler nicht SimileAjax.DOM.cancelEvent(domEvt) Anruf, den ich auf den Namen basierend assume bricht die sprudelnden von Veranstaltungen;
  • Nur um etwas komplizierter s, was ich eigentlich mache ein Timeout beginnt, wenn nicht durch eine moustout storniert das Pop-up zeigt, soll dies werden Pop-ups verhindern annoyingly Flimmern aber ärgerlicherweise die umgekehrte Wirkung.

Ich werde einen anderen Poke an sie und sehen, ob ich heraus kann arbeiten, wo ich falsch werde. : -)

War es hilfreich?

Lösung

Ja, Javascript ist single-threaded. Auch mit Browsern wie Google Chrome, gibt es einen Thread pro Tab.

Ohne zu wissen, wie Sie versuchen, ein Pop-up von einem anderen zu beenden, ist es schwer zu sagen, was die Ursache des Problems ist.

Wenn Ihr DIVs anderen innerhalb eines verschachtelt sind, können Sie eine Ereignispropagierung Thema.

Andere Tipps

Ich weiß nicht, die Bibliothek, die Sie verwenden, aber wenn Sie nur einen Tooltip somesort versuchen, zu einer Zeit anzuzeigen ... ein Fliehgewicht-Objekt verwenden. Im Grunde ein Fliegengewicht ist etwas, das einmal gemacht und verwenden immer und immer wieder. Denken Sie an eine Singleton-Klasse. So rufen Sie eine Klasse statisch, dass, wenn zunächst automatisch aufgerufen erstellt ein Objekt von sich selbst und speichert sie. Man dies geschieht jedes statische alle Verweise das gleiche Objekt und aus diesem Grund Sie nicht mehrere Tooltips oder Konflikte bekommen.

Ich verwende ExtJS und sie tun Tooltips und Meldungsfelder, da beide Fliegengewicht Elemente. Ich hoffe, dass Ihr Frameworks Fliegengewicht Elemente hatte auch, sonst werden Sie nur Ihre eigene Singleton machen und nennt es.

Es ist single threaded in Browsern. Eventhandler werden asynchroniously in einem Thread, nicht blockierende bedeutet jedoch nicht ausgeführt Allways multithreaded. Ist einer Ihrer divs ein Kind des anderen? Da Ereignisse verbreitete sich wie Blasen im DOM-Baum von Kind zu Eltern.

ähnlich wie pkaeding sagte, ist es schwer, das Problem zu erraten, ohne Ihren Markup und Skript zu sehen; Ich würde jedoch wagen zu sagen, dass Sie nicht richtig die Ereignispropagierung stoppen und / oder du bist nicht richtig das bestehende Element versteckt. Ich weiß nicht, ob Sie einen Rahmen oder nicht verwenden, aber hier ist eine mögliche Lösung mit Prototype:

// 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));

Natürlich ist dies weiter verallgemeinert werden könnte, indem alle Elemente mit, sagen wir, der gleichen Klasse bekommen, Iterieren durch sie, und das gleiche Ereignis Anwendung Funktion für jeden von ihnen Handhabung.

So oder so, hoffentlich, das hilft.

Zur Info: Ab Firefox 3 gibt es eine Änderung ziemlich relevant zu dieser Diskussion: Ausführungs-Threads verursachen synchrone XMLHttpRequest-Anfragen dadurch lösen (aus diesem Grunde die Schnittstelle während synchroner Anforderungen dort nicht einfrieren) und die Ausführung fortgesetzt. Beim synchronen Anforderungsbeendigungs weiterhin ihrem Gewinde auch. Sie werden nicht zur gleichen Zeit ausgeführt werden, jedoch auf der Annahme, dass unter Berufung einzelner Thread anhält, während ein synchrones Verfahren (Anfrage) geschieht nicht anwendbar ist, nicht mehr.

Es könnte sein, dass die Anzeige nicht schnell genug ist erfrischend. In Abhängigkeit von der JS-Bibliothek Sie verwenden, können Sie möglicherweise eine kleine Verzögerung setzen auf dem Pop-up „Show-Effekt“.

Hier ist die Arbeitsversion, mehr oder weniger. Wenn Elemente erstellen legen wir mouseover Ereignis:

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

Dies erfordert eine Funktion, die einen Timeout setzt (vorbestehenden Timeouts für einen anderen Artikel aufgehoben wird zuerst):

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);
}

Dies wiederum zeigt die Blase, wenn es abgebrochen feuert, bevor sie:

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(...);
};

Das scheint jetzt arbeiten ich das Timeout auf 200 ms statt 100 ms eingestellt haben. Nicht sicher, warum ein zu kurze Timeout bewirkt, dass das Multi-Blase, was geschehen kann, aber ich denke, Warteschlangen von Fenstern Ereignissen oder etwas könnte noch passieren, während die neu hinzugefügten Elemente werden angelegt sind.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top