2010-11-16 23 views
6

J'ai dans une page HTML, un élément qui apparaît plusieurs fois et qui exécute le même JS. Le problème est, je veux qu'il fasse une fonction spécifique seulement s'il était le premier à l'exécuter (ses frères et sœurs ne l'ont jamais exécuté - ENCORE).Comment créer un sémaphore entre des éléments HTML chargés async

J'ai besoin de sémaphore pour synchroniser entre eux. Je ne peux pas savoir comment déclarer une variable et faire un sémaphore de cette manière dans JS.

Répondre

7

Il y a beaucoup d'approches.

Vous devez mettre un drapeau quelque part. En l'absence de toute autre chose, vous pouvez le mettre sur window, mais utiliser un nom qui est peu susceptible d'entrer en conflit avec quoi que ce soit d'autre.

Alors le JavaScript est assez simple:

if (!window.myUniqueNameFlag) { 
    window.myUniqueNameFlag = true; 
    // Do your processing 
} 

Mais encore une fois, de mettre les choses sur window n'est pas idéal si vous pouvez l'éviter, bien qu'il soit très pratique courante. (Toute fonction ou variable que vous déclarez à portée globale est une propriété de window.)

Si votre fonction est déjà déclarée à l'échelle globale (et occupe donc déjà un symbole), vous pouvez le faire pour éviter de créer un second symbole. Au lieu de:

function foo() { 
    // ...your processing... 
} 

Pour ce faire:

var foo = (function() { 
    var flag = flase; 

    function foo() { 
     if (!flag) { 
      flag = true; 
      // ...your processing... 
     } 
    } 

    return foo; 
})(); 

Cela semble compliqué, mais ce n'est pas vraiment: Nous définissons une fonction anonyme, au sein de laquelle nous définissons une variable et une fonction imbriquée, nous retournons la référence de fonction imbriquée et l'affecter à la variable externe foo. Vous pouvez appeler foo et vous obtiendrez la fonction imbriquée. La fonction imbriquée a une référence durable à la variable flag car il s'agit d'un closure over the variable, mais personne d'autre ne peut le voir. C'est complètement privé.

Une troisième option est d'utiliser simplement un drapeau sur l'objet lui-même fonction:

function foo() { 
    if (!foo.flag) { 
     foo.flag = true; 
     // ...do your processing... 
    } 
} 

Les fonctions sont tout simplement des objets avec la possibilité d'être appelés, de sorte que vous pouvez ajouter des propriétés à leur disposition.

+2

Ce n'est pas une opération atomique. théoriquement, les deux éléments peuvent passer la condition if avant d'affecter la variable – Himberjack

+5

@oshafran: JavaScript sur les navigateurs est garanti être monothread sauf l'utilisation du nouveau [web workers] (http://www.w3.org/TR/workers /) stuff, qui nécessite une syntaxe explicite. Donc, le ** ci-dessus est ** atomique sur un navigateur. Si vous utilisiez un autre environnement, et * si * cet environnement était multithread, vous utiliseriez les mécanismes de synchronisation fournis par l'environnement. Mais vous avez dit ce navigateur, donc aucun n'est nécessaire. –

+0

Merci! .............. – Himberjack