API de bloqueos web

Coordinar el trabajo y el uso de recursos entre diferentes procesos.

Es hora de encerrarse

Las funciones asincrónicas en Javascript no son realmente paralelas. A partir de ES2017, Javascript admite llamadas a funciones simultáneas. Madhavan Nagarajan resume muy bien la diferencia en la siguiente declaración (el enlace se puede encontrar en el apéndice).

La concurrencia se trata de lidiar con muchas cosas a la vez. El paralelismo consiste en hacer muchas cosas a la vez.

La implementación de la concurrencia de Javascript se reduce en su funcionalidad para permitir el uso de una API simple y muy robusta. Las funciones asíncronas no se pueden interrumpir y no tienen un concepto de propiedades volátiles cuando se trata de acceder a la misma variable mediante diferentes llamadas asíncronas. La implementación detallada de las funciones asíncronas de ES2017 está fuera del alcance de este artículo, pero el punto principal que quiero transmitir es que, hasta ahora, el paralelismo no estaba integrado en Javascript y la web y, por lo tanto, no había un manejo especial de mutaciones paralelas del misma entidad. Pero eso cambia ahora con la introducción de la "API de Web Locks".

Uno para todos y todos para uno

Ahora que las aplicaciones web progresivas le ofrecen verdaderas arquitecturas multiproceso con la introducción de WebWorkers y ServiceWorker, las cosas han cambiado. El verdadero paralelismo es posible en las aplicaciones web y, por lo tanto, surge el deseo de herramientas más sofisticadas para trabajar con código paralelo.

Un bloqueo es un mecanismo para solicitar acceso a recursos y tener la garantía de que solo un proceso en cualquier momento realmente tiene acceso. Bloquear los recursos de esta manera evita un gran conjunto de áreas de conflicto que podrían surgir.

Un recurso es solo un espacio de nombres, identificado por una cadena. Y su solicitud para acceder al recurso es tan simple, ya que solo necesita el ID y una devolución de llamada de función, probablemente asincrónica, para implementar la "API de Web Lock". Cuando una función asincrónica ha finalizado, el bloqueo se libera y otras solicitudes pueden acceder a ella nuevamente.

/*
 * A simple demonstration of the Web Lock API.
 * Note that this example has been taken from
 * MDN's awesome documentation, linked in the
 * addendum.
 */
async function foo(){
  // A common async function that you already know.
  const data = await getData();

  // Request the lock.
  // Note that we can simply await the locked call!
  await navigator.locks.request('lock_resource_id', async lock => {
    // The lock has been acquired.
    // At this point, this call has exlusive access 
    // to the resource 'lock_resource_id'.
    await updateDb(data);
    // Now the lock will be released.
  });
  
  // The lock has been released.
  // Continuse with plain async calls.
  await updateUi();
}

Debido al estado experimental de esta nueva API, debe tratarla como una característica opcional en su código con una alternativa válida disponible.

/**
 * Due to the usage of web locks in core parts
 * of your app, actually using the API this way
 * might introduce more problems then it could solve.
 * 
 * Therefore a thorough specification in your app
 * has to be implementation before using this feature.
 */
async function update(){
  if(navigator?.locks){
    // Run logic with lock.
  } else {
    // Use fallback.
  }
}

Para ilustrar mejor esta nueva API, veremos un ejemplo simple. Supongamos que tiene una PWA multiproceso con su proceso principal y dos WebWorkers. Su aplicación también usa un IndexDB, con código personalizado que sincroniza los cambios hacia y desde la base de datos con la nube. Usando la "API de Web Lock" en este escenario, cada proceso puede solicitar acceso al bloqueo definido para sincronizar los cambios en la base de datos, asegurándose de que no se ejecuten otras mutaciones durante esta llamada.

Tenga en cuenta que la "API de Web Lock" no se trata tanto de mutar una sola variable sin efectos secundarios en su aplicación web (aunque claramente puede ser un caso de uso), sino más sobre el manejo de llamadas a funciones en una arquitectura paralela que de otro modo conduciría a efectos secundarios negativos.

Mucho mas para aprender

Este artículo solo brindó una introducción a la nueva "API de Web Locks", que actualmente se encuentra en estado experimental y es compatible principalmente con navegadores basados en Chromium. La API ofrece más opciones que se describen aquí y vale la pena echarle un vistazo.