hombre de las cavernas inteligentes
¿Cómo podría algo equivalente a lock
en C# implementarse en JavaScript?
Entonces, para explicar lo que estoy pensando, un caso de uso simple es:
El usuario hace clic en el botón B
. B
genera un evento onclick. Si B
es en event-state
el evento espera B
estar en ready-state
antes de propagarse. Si B
es en ready-state
, B
está bloqueado y configurado para event-state
, entonces el evento se propaga. Cuando se completa la propagación del evento, B
se establece en ready-state
.
Pude ver cómo se podría hacer algo parecido a esto, simplemente agregando y eliminando la clase ready-state
desde el botón. Sin embargo, el problema es que un usuario puede hacer clic en un botón dos veces seguidas más rápido de lo que se puede configurar la variable, por lo que este intento de bloqueo fallará en algunas circunstancias.
¿Alguien sabe cómo implementar un bloqueo que no fallará en JavaScript?
JoshRivers
El bloqueo es una idea cuestionable en JS que está destinado a no tener subprocesos y no necesita protección de concurrencia. Está buscando combinar llamadas en ejecución diferida. El patrón que sigo para esto es el uso de devoluciones de llamada. Algo como esto:
var functionLock = false;
var functionCallbacks = [];
var lockingFunction = function (callback) {
if (functionLock) {
functionCallbacks.push(callback);
} else {
$.longRunning(function(response) {
while(functionCallbacks.length){
var thisCallback = functionCallbacks.pop();
thisCallback(response);
}
});
}
}
También puede implementar esto utilizando detectores de eventos DOM o una solución pubsub.
-
¿podría proporcionar documentación de referencia que justifique su declaración de que “JS está destinado a no tener subprocesos y no necesita protección de concurrencia”? Me gustaría leer más sobre esto.
– hombre de las cavernas inteligente
5 de junio de 2011 a las 0:02
-
+1: dado que Node.js (servidor web de JavaScript) se creó para aprovechar el mecanismo de devolución de llamada y subproceso único de JavaScript, estoy de acuerdo en que no debe preocuparse por bloquear una propiedad, ya que no habrá condición de carrera.
– Fenton
8 de junio de 2011 a las 15:05
-
¿De qué biblioteca es $.longRunning? No está en (actual) jQuery.
– Quantum7
10 mayo 2017 a las 11:32
-
¿Cuándo se supone que debe configurarse functionLock?
–Elton Santana
21 de junio de 2017 a las 18:59
-
“JS que está destinado a ser sin subprocesos y que no necesita concurrencia” es dudoso. JS no usa la concurrencia preventiva, pero le permite usar la concurrencia cooperativa (devolución de llamada o basada en async/await). Definitivamente puede tener condiciones de carrera al usarlas y es posible que desee usar una abstracción mutex para evitarlas.
– ysdx
14 de febrero de 2018 a las 8:56
mike samuel
JavaScript es, con muy pocas excepciones (XMLHttpRequest
onreadystatechange
controladores en algunas versiones de Firefox) bucle de eventos concurrente. Por lo tanto, no debe preocuparse por el bloqueo en este caso.
JavaScript tiene un modelo de concurrencia basado en un “bucle de eventos”. Este modelo es bastante diferente al modelo en otros lenguajes como C o Java.
…
Un tiempo de ejecución de JavaScript contiene una cola de mensajes, que es una lista de mensajes que se van a procesar. A cada mensaje se le asocia una función. Cuando la pila está vacía, se saca un mensaje de la cola y se procesa. El procesamiento consiste en llamar a la función asociada (y, por lo tanto, crear un marco de pila inicial). El procesamiento del mensaje finaliza cuando la pila vuelve a estar vacía.
…
Cada mensaje se procesa completamente antes de que se procese cualquier otro mensaje. Esto ofrece algunas buenas propiedades al razonar sobre su programa, incluido el hecho de que cada vez que se ejecuta una función, no se puede adelantar y se ejecutará por completo antes de que se ejecute cualquier otro código (y puede modificar los datos que manipula la función). Esto difiere de C, por ejemplo, donde si una función se ejecuta en un subproceso, se puede detener en cualquier punto para ejecutar otro código en otro subproceso.
Una desventaja de este modelo es que si un mensaje tarda demasiado en completarse, la aplicación web no puede procesar las interacciones del usuario, como hacer clic o desplazarse. El navegador mitiga esto con el cuadro de diálogo “un script está tardando demasiado en ejecutarse”. Una buena práctica a seguir es acortar el procesamiento de mensajes y, si es posible, dividir un mensaje en varios mensajes.
Para obtener más enlaces sobre la concurrencia de bucles de eventos, consulte mi
-
Y con Trabajadores web (subprocesos que no son de interfaz de usuario) en javascript, cada objeto clones antes de enviar a otro trabajador (subproceso) o subproceso de interfaz de usuario, el objeto tiene diferentes instancias en diferentes subprocesos y cada subproceso tiene un ciclo de eventos propio y finalmente estoy de acuerdo con la respuesta de Mike como una respuesta útil. gracias mike
–Ehsan Mohammadi
21 de marzo de 2019 a las 19:26
he tenido exito promesa mutex.
Estoy de acuerdo con otras respuestas en las que es posible que no necesite bloquear su caso. Pero no es cierto que uno nunca necesite bloquearse en Javascript. Necesita exclusividad mutua al acceder a recursos externos que no manejan la simultaneidad.
-
Gracias cosa muy necesaria.
– Dmitrij Polianina
6 de febrero de 2019 a las 8:04
Los bloqueos son un concepto necesario en un sistema de subprocesos múltiples. Incluso con subprocesos de trabajadores, los mensajes se envían por valor entre los trabajadores, por lo que no es necesario bloquearlos.
Sospecho que solo necesita configurar un semáforo (sistema de señalización) entre sus botones.
Aquí hay un mecanismo de bloqueo simple, implementado a través del cierre.
const createLock = () => {
let lockStatus = false
const release = () => {
lockStatus = false
}
const acuire = () => {
if (lockStatus == true)
return false
lockStatus = true
return true
}
return {
lockStatus: lockStatus,
acuire: acuire,
release: release,
}
}
lock = createLock() // create a lock
lock.acuire() // acuired a lock
if (lock.acuire()){
console.log("Was able to acuire");
} else {
console.log("Was not to acuire"); // This will execute
}
lock.release() // now the lock is released
if(lock.acuire()){
console.log("Was able to acuire"); // This will execute
} else {
console.log("Was not to acuire");
}
lock.release() // Hey don't forget to release
Xerxess
¿Por qué no desactivas el botón y lo activas después de terminar el evento?
<input type="button" id="xx" onclick="checkEnableSubmit('true');yourFunction();">
<script type="text/javascript">
function checkEnableSubmit(status) {
document.getElementById("xx").disabled = status;
}
function yourFunction(){
//add your functionality
checkEnableSubmit('false');
}
</script>
¡Feliz codificación!
Kadir Ercétin
Alguna adición a la respuesta de JoshRiver según mi caso;
var functionCallbacks = [];
var functionLock = false;
var getData = function (url, callback) {
if (functionLock) {
functionCallbacks.push(callback);
} else {
functionLock = true;
functionCallbacks.push(callback);
$.getJSON(url, function (data) {
while (functionCallbacks.length) {
var thisCallback = functionCallbacks.pop();
thisCallback(data);
}
functionLock = false;
});
}
};
// Usage
getData("api/orders",function(data){
barChart(data);
});
getData("api/orders",function(data){
lineChart(data);
});
Habrá solo una llamada api y estas dos funciones consumirán el mismo resultado.
Se agradecerán las respuestas que tengan en cuenta la ejecución JS paralela (es decir, como en IE9).
– perro naranja
18 de marzo de 2011 a las 0:02
@smart Entonces, desea pausar temporalmente la propagación del evento actual hasta que se complete la propagación de un evento anterior. No creo que eso se pueda hacer. Podría hacer esto: descartar el evento y luego disparar otro cuando el evento anterior haya terminado de propagarse.
– Sime Vidas
18 de marzo de 2011 a las 0:47
@OrangeDog: solo escuché que IE9 intenta usar un núcleo dedicado para la compilación, nada sobre la ejecución en paralelo, ¿puede citar una fuente?
– Brandón
18 de marzo de 2011 a las 0:55
@Brandon: eso podría significar, como sugiere, paralelo al renderizador, en lugar de paralelo a sí mismo.
– perro naranja
18 de marzo de 2011 a las 13:54
Relacionado: stackoverflow.com/questions/6266868/…
–David Murdoch
7 junio 2011 a las 14:35