Explorando el potencial de los trabajadores web para subprocesos múltiples en la Web

 

 

 

  • SmashingConf Freiburg 2024
  • Deploy Fast. Deploy Smart

  • Índice
    1. Importancia y beneficios de los trabajadores web para subprocesos múltiples en la Web
      1. Utilización mejorada de recursos
      2. Mayor estabilidad y confiabilidad
      3. Seguridad mejorada
      4. Mejor utilización de recursos
    2. Aplicaciones prácticas de los trabajadores web
      1. Descarga de trabajo intensivo de CPU
      2. Manejo de solicitudes de red
      3. Procesamiento en paralelo
    3. Limitaciones y consideraciones
      1. Soporte del navegador
      2. Acceso limitado al DOM
      3. Gastos generales de comunicación
      4. Herramientas de depuración limitadas
      5. Complejidad del código
    4. Estrategias para mitigar posibles problemas con los trabajadores web
      1. Minimice los gastos generales de comunicación con el procesamiento por lotes de mensajes
      2. Evite los métodos sincrónicos
      3. Sea consciente del uso de la memoria
      4. Compatibilidad del navegador
    5. Conclusión

    Multithreading es una técnica importante utilizada en el desarrollo de software moderno para mejorar el rendimiento y la capacidad de respuesta de las aplicaciones. Sin embargo, no es una práctica común en la web debido a la naturaleza de un solo subproceso de JavaScript. Para superar esta limitación, se introdujeron Web Workers como una forma de habilitar esta técnica en aplicaciones web. En este artículo, Sarah Oke Okolo explora la importancia de los Web Workers para los subprocesos múltiples en la web, incluidas las limitaciones y consideraciones de su uso y las estrategias para mitigar los posibles problemas asociados con los Web Workers.

     

    Los Web Workers son una característica poderosa del desarrollo web moderno y se introdujeron como parte de la especificación HTML5 en 2009 . Fueron diseñados para proporcionar una forma de ejecutar código JavaScript en segundo plano, separado del hilo de ejecución principal de una página web, para mejorar el rendimiento y la capacidad de respuesta.

    El hilo principal es el contexto de ejecución único que es responsable de representar la interfaz de usuario, ejecutar el código JavaScript y manejar las interacciones del usuario. En otras palabras, JavaScript es de "un solo subproceso" . Esto significa que cualquier tarea que requiera mucho tiempo, como cálculos complejos o procesamiento de datos que se ejecute, bloquearía el hilo principal y provocaría que la interfaz de usuario se congelara y dejara de responder.

    Aquí es donde entran los trabajadores web.

    Los Web Workers se implementaron como una forma de abordar este problema al permitir que las tareas que consumen mucho tiempo se ejecuten en un hilo separado, llamado hilo de trabajo . Esto permitió que el código JavaScript se ejecutara en segundo plano sin bloquear el hilo principal y provocar que la página dejara de responder.

    Crear un trabajador web en JavaScript no es una tarea muy complicada. Los siguientes pasos proporcionan un punto de partida para integrar un trabajador web en su aplicación:

    1. Cree un nuevo archivo JavaScript que contenga el código que desea ejecutar en el hilo de trabajo. Este archivo no debe contener ninguna referencia al DOM, ya que no tendrá acceso a él.
    2. En su archivo JavaScript principal, cree un nuevo objeto de trabajo usando el Workerconstructor. Este constructor toma un único argumento, que es la URL del archivo JavaScript que creó en el paso 1.
      const worker = new Worker('worker.js');
    3. Agregue detectores de eventos al objeto de trabajo para manejar los mensajes enviados entre el hilo principal y el hilo de trabajo. El onmessagecontrolador de eventos se usa para manejar mensajes enviados desde el hilo de trabajo, mientras que el postMessagemétodo se usa para enviar mensajes al hilo de trabajo.
      worker.onmessage = function(event) { console.log('Worker said: ' + event.data);};worker.postMessage('Hello, worker!');
    4. En su archivo JavaScript de trabajo, agregue un detector de eventos para manejar los mensajes enviados desde el hilo principal utilizando la onmessagepropiedad del selfobjeto. Puede acceder a los datos enviados con el mensaje utilizando la event.datapropiedad.
      self.onmessage = function(event) { console.log('Main thread said: ' + event.data); self.postMessage('Hello, main thread!');};

    Ahora ejecutemos la aplicación web y probemos al trabajador. Deberíamos ver mensajes impresos en la consola indicando que se enviaron y recibieron mensajes entre el hilo principal y el hilo de trabajo.

     

    ( Vista previa grande )

    Una diferencia clave entre los Web Workers y el hilo principal es que los Web Workers no tienen acceso al DOM ni a la UI . Esto significa que no pueden manipular directamente los elementos HTML de la página ni interactuar con el usuario.

    Web Workers están diseñados para realizar tareas que no requieren acceso directo a la interfaz de usuario, como procesamiento de datos, manipulación de imágenes o cálculos.

    Otra diferencia importante es que los Web Workers están diseñados para ejecutarse en un entorno aislado , separado del hilo principal, lo que significa que tienen acceso limitado a los recursos del sistema y no pueden acceder a ciertas API, como las API localStorageo . sessionStorageSin embargo, pueden comunicarse con el hilo principal a través de un sistema de mensajería, lo que permite el intercambio de datos entre los dos hilos.

    Importancia y beneficios de los trabajadores web para subprocesos múltiples en la Web

    Web Workers proporciona una forma para que los desarrolladores web logren subprocesos múltiples en la web, lo cual es crucial para crear aplicaciones web de alto rendimiento. Al permitir que las tareas que consumen mucho tiempo se ejecuten en segundo plano, separadas del hilo principal, Web Workers mejoran la capacidad de respuesta general de las páginas web y permiten una experiencia de usuario más fluida. A continuación se detallan algunas de la importancia y los beneficios de Web Workers para subprocesos múltiples en la Web.

    Utilización mejorada de recursos

    Al permitir que las tareas que consumen mucho tiempo se ejecuten en segundo plano, Web Workers hace un uso más eficiente de los recursos del sistema, lo que permite un procesamiento de datos más rápido y eficiente y mejora el rendimiento general. Esto es especialmente importante para aplicaciones web que implican grandes cantidades de procesamiento de datos o manipulación de imágenes, ya que los trabajadores web pueden realizar estas tareas sin afectar la interfaz de usuario.

     

    Mayor estabilidad y confiabilidad

    Al aislar las tareas que consumen mucho tiempo en subprocesos de trabajo separados, Web Workers ayuda a evitar fallas y errores que pueden ocurrir al ejecutar grandes cantidades de código en el subproceso principal. Esto facilita a los desarrolladores escribir aplicaciones web estables y confiables, lo que reduce la probabilidad de frustración del usuario o pérdida de datos.

    Seguridad mejorada

    Web Workers se ejecuta en un entorno aislado del hilo principal, lo que ayuda a mejorar la seguridad de las aplicaciones web. Este aislamiento evita que el código malicioso acceda o modifique los datos en el hilo principal u otros trabajadores web, lo que reduce el riesgo de violaciones de datos u otras vulnerabilidades de seguridad.

    Mejor utilización de recursos

    Web Workers puede ayudar a mejorar la utilización de recursos al liberar el hilo principal para manejar la entrada del usuario y otras tareas mientras los Web Workers manejan cálculos que consumen mucho tiempo en segundo plano. Esto puede ayudar a mejorar el rendimiento general del sistema y reducir la probabilidad de fallas o errores. Además, al aprovechar múltiples núcleos de CPU, Web Workers puede hacer un uso más eficiente de los recursos del sistema, lo que permite un procesamiento de datos más rápido y eficiente.

    Web Workers también permite un mejor equilibrio de carga y escalado de aplicaciones web. Al permitir que las tareas se ejecuten en paralelo a través de múltiples subprocesos de trabajo, Web Workers puede ayudar a distribuir la carga de trabajo de manera uniforme entre múltiples núcleos o procesadores , lo que permite un procesamiento de datos más rápido y eficiente. Esto es particularmente importante para las aplicaciones web que experimentan mucho tráfico o demanda, ya que los trabajadores web pueden ayudar a garantizar que la aplicación pueda manejar una mayor carga sin afectar el rendimiento.

    Aplicaciones prácticas de los trabajadores web

    Exploremos algunas de las aplicaciones más comunes y útiles de Web Workers. Ya sea que esté creando una aplicación web compleja o un sitio web simple, comprender cómo aprovechar Web Workers puede ayudarlo a mejorar el rendimiento y brindar una mejor experiencia de usuario.

    Descarga de trabajo intensivo de CPU

    Supongamos que tenemos una aplicación web que necesita realizar un gran cálculo con uso intensivo de CPU. Si realizamos este cálculo en el hilo principal, la interfaz de usuario dejará de responder y la experiencia del usuario se verá afectada. Para evitar esto, podemos utilizar un Web Worker para realizar el cálculo en segundo plano.

    // Create a new Web Worker.const worker = new Worker('worker.js');// Define a function to handle messages from the worker.worker.onmessage = function(event) { const result = event.data; console.log(result);};// Send a message to the worker to start the computation.worker.postMessage({ num: 1000000 });// In worker.js:// Define a function to perform the computation.function compute(num) { let sum = 0; for (let i = 0; i num; i++) { sum += i; } return sum;}// Define a function to handle messages from the main thread.onmessage = function(event) { const num = event.data.num; const result = compute(num); postMessage(result);};

    En este ejemplo, creamos un nuevo trabajador web y definimos una función para manejar los mensajes del trabajador. Luego enviamos un mensaje al trabajador con un parámetro ( num) que especifica el número de iteraciones a realizar en el cálculo. El trabajador recibe este mensaje y realiza el cálculo en segundo plano. Cuando se completa el cálculo, el trabajador envía un mensaje al hilo principal con el resultado. El hilo principal recibe este mensaje y registra el resultado en la consola.

     

    ( Vista previa grande )

    Esta tarea consiste en sumar todos los números desde 0hasta un número determinado. Si bien esta tarea es relativamente simple y directa para números pequeños, puede resultar computacionalmente intensiva para números muy grandes.

    En el código de ejemplo que usamos anteriormente, pasamos el número 1000000a la compute()función en Web Worker. Esto significa que la función de cálculo deberá sumar todos los números del 0 al un millón. Esto implica una gran cantidad de operaciones adicionales y puede tardar una cantidad significativa de tiempo en completarse, especialmente si el código se ejecuta en una computadora más lenta o en una pestaña del navegador que ya está ocupada con otras tareas.

    Al descargar esta tarea a un Web Worker, el hilo principal de la aplicación puede continuar ejecutándose sin problemas sin ser bloqueado por la tarea computacionalmente intensiva. Esto permite que la interfaz de usuario siga respondiendo y garantiza que otras tareas, como la entrada del usuario o las animaciones, puedan manejarse sin demora.

    Manejo de solicitudes de red

    Consideremos un escenario en el que una aplicación web necesita iniciar una cantidad significativa de solicitudes de red. Realizar estas solicitudes dentro del hilo principal podría hacer que la interfaz de usuario deje de responder y resulte en una mala experiencia de usuario. Para evitar este problema, podemos utilizar Web Workers para manejar estas solicitudes en segundo plano. Al hacerlo, el hilo principal permanece libre para ejecutar otras tareas mientras Web Worker maneja las solicitudes de red simultáneamente, lo que resulta en un mejor rendimiento y una mejor experiencia de usuario. Cursos gratis en Youtube

    // Create a new Web Worker.const worker = new Worker('worker.js');// Define a function to handle messages from the worker.worker.onmessage = function(event) { const response = event.data; console.log(response);};// Send a message to the worker to start the requests.worker.postMessage({ urls: ['https://api.example.com/foo', 'https://api.example.com/bar'] });// In worker.js:// Define a function to handle network requests.function request(url) { return fetch(url).then(response = response.json());}// Define a function to handle messages from the main thread.onmessage = async function(event) { const urls = event.data.urls; const results = await Promise.all(urls.map(request)); postMessage(results);};

    En este ejemplo, creamos un nuevo trabajador web y definimos una función para manejar los mensajes del trabajador. Luego enviamos un mensaje al trabajador con una serie de URL para solicitar. El trabajador recibe este mensaje y realiza las solicitudes en segundo plano utilizando la fetchAPI . Cuando se completan todas las solicitudes, el trabajador envía un mensaje al hilo principal con los resultados. El hilo principal recibe este mensaje y registra los resultados en la consola.

     

    Procesamiento en paralelo

    Supongamos que tenemos una aplicación web que necesita realizar una gran cantidad de cálculos independientes. Si realizamos estos cálculos en secuencia en el hilo principal, la interfaz de usuario dejará de responder y la experiencia del usuario se verá afectada. Para evitar esto, podemos utilizar un Web Worker para realizar los cálculos en paralelo.

    // Create a new Web Worker.const worker = new Worker('worker.js');// Define a function to handle messages from the worker.worker.onmessage = function(event) { const result = event.data; console.log(result);};// Send a message to the worker to start the computations.worker.postMessage({ nums: [1000000, 2000000, 3000000] });// In worker.js:// Define a function to perform a single computation.function compute(num) { let sum = 0; for (let i = 0; i num; i++) { sum += i;} return sum;}// Define a function to handle messages from the main thread.onmessage = function(event) { const nums = event.data.nums; const results = nums.map(compute); postMessage(results);};

    En este ejemplo, creamos un nuevo trabajador web y definimos una función para manejar los mensajes del trabajador. Luego enviamos un mensaje al trabajador con una serie de números para calcular. El trabajador recibe este mensaje y realiza los cálculos en paralelo utilizando el método del mapa. Cuando se completan todos los cálculos, el trabajador envía un mensaje al hilo principal con los resultados. El hilo principal recibe este mensaje y registra los resultados en la consola.

    Limitaciones y consideraciones

    Los trabajadores web son una herramienta poderosa para mejorar el rendimiento y la capacidad de respuesta de las aplicaciones web, pero también tienen algunas limitaciones y consideraciones que debes tener en cuenta al usarlos. Éstos son algunos de los más importantes:

    Soporte del navegador

    Los trabajadores web son compatibles con los principales navegadores, incluidos Chrome, Firefox, Safari y Edge. Sin embargo, todavía hay otros navegadores que no son compatibles con los trabajadores web o que pueden tener un soporte limitado.

    Para obtener una descripción más detallada de la compatibilidad del navegador, consulte ¿Puedo utilizarlo ?

    Es importante que verifique la compatibilidad del navegador con cualquier función antes de usarla en el código de producción y pruebe su aplicación minuciosamente para garantizar la compatibilidad.

    Acceso limitado al DOM

    Los trabajadores web se ejecutan en un hilo separado y no tienen acceso al DOM ni a otros objetos globales en el hilo principal. Esto significa que no puede manipular directamente el DOM desde un trabajador web ni acceder a objetos globales como ventanas o documentos.

    Para solucionar esta limitación, puede utilizar el postMessagemétodo para comunicarse con el hilo principal y actualizar el DOM o acceder a objetos globales indirectamente. Por ejemplo, puede enviar datos al hilo principal utilizando postMessagey luego actualizar el DOM u objetos globales en respuesta al mensaje.

     

    Alternativamente, existen algunas bibliotecas que ayudan a resolver este problema. Por ejemplo, la biblioteca WorkerDOM le permite ejecutar el DOM en un trabajador web, lo que permite una representación de páginas más rápida y un rendimiento mejorado.

    Gastos generales de comunicación

    Los trabajadores web se comunican con el hilo principal utilizando este postMessagemétodo y, como resultado, podrían introducir una sobrecarga de comunicación, que se refiere a la cantidad de tiempo y recursos necesarios para establecer y mantener la comunicación entre dos o más sistemas informáticos, como por ejemplo entre un trabajador web y el hilo principal de una aplicación web. Esto podría provocar un retraso en el procesamiento de mensajes y potencialmente ralentizar la aplicación. Para minimizar esta sobrecarga, solo debes enviar datos esenciales entre hilos y evitar enviar grandes cantidades de datos o mensajes frecuentes .

    Herramientas de depuración limitadas

    Depurar Web Workers puede ser más desafiante que depurar código en el hilo principal, ya que hay menos herramientas de depuración disponibles. Para facilitar la depuración, puede utilizar la consoleAPI para registrar mensajes del hilo de trabajo y utilizar herramientas de desarrollo del navegador para inspeccionar los mensajes enviados entre hilos.

    Complejidad del código

    El uso de Web Workers puede aumentar la complejidad de su código, ya que necesita administrar la comunicación entre subprocesos y garantizar que los datos se pasen correctamente. Esto puede hacer que sea más difícil escribir, depurar y mantener su código, por lo que debe considerar cuidadosamente si es necesario utilizar trabajadores web para su aplicación.

    Estrategias para mitigar posibles problemas con los trabajadores web

    Web Workers son una herramienta poderosa para mejorar el rendimiento y la capacidad de respuesta de las aplicaciones web. Sin embargo, al utilizar Web Workers, pueden surgir varios problemas potenciales. A continuación se presentan algunas estrategias para mitigar estos problemas:

    Minimice los gastos generales de comunicación con el procesamiento por lotes de mensajes

    El procesamiento por lotes de mensajes implica agrupar varios mensajes en un solo mensaje por lotes, lo que puede ser más eficiente que enviar mensajes individuales por separado. Este enfoque reduce la cantidad de viajes de ida y vuelta entre el hilo principal y los Web Workers. Puede ayudar a minimizar la sobrecarga de comunicación y mejorar el rendimiento general de su aplicación web.

    Para implementar el procesamiento por lotes de mensajes, puede utilizar una cola para acumular mensajes y enviarlos juntos como un lote cuando la cola alcanza un determinado umbral o después de un período de tiempo determinado. A continuación se muestra un ejemplo de cómo puede implementar el procesamiento por lotes de mensajes en su Web Worker:

    // Create a message queue to accumulate messages.const messageQueue = [];// Create a function to add messages to the queue.function addToQueue(message) { messageQueue.push(message); // Check if the queue has reached the threshold size. if (messageQueue.length = 10) { // If so, send the batched messages to the main thread. postMessage(messageQueue); // Clear the message queue. messageQueue.length = 0; }}// Add a message to the queue.addToQueue({type: 'log', message: 'Hello, world!'});// Add another message to the queue.addToQueue({type: 'error', message: 'An error occurred.'});

    En este ejemplo, creamos una cola de mensajes para acumular mensajes que deben enviarse al hilo principal. Cada vez que se agrega un mensaje a la cola usando la addToQueuefunción, verificamos si la cola ha alcanzado el tamaño umbral (en este caso, diez mensajes). Si es así, enviamos los mensajes por lotes al hilo principal utilizando el postMessagemétodo. Finalmente, limpiamos la cola de mensajes para prepararla para el siguiente lote.

     

    Al agrupar mensajes por lotes de esta manera, podemos reducir la cantidad total de mensajes enviados entre el hilo principal y los Web Workers.

    Evite los métodos sincrónicos

    Estas son funciones u operaciones de JavaScript que bloquean la ejecución de otro código hasta que se completen. Los métodos sincrónicos pueden bloquear el hilo principal y hacer que su aplicación deje de responder. Para evitar esto, debe evitar el uso de métodos sincrónicos en su código de Web Worker. En su lugar, utilice métodos asincrónicos como setTimeout()o setInterval()para realizar cálculos de larga duración.

    Aquí hay una pequeña demostración:

    // In the workerself.addEventListener('message', (event) = { if (event.data.action === 'start') { // Use a setTimeout to perform some computation asynchronously. setTimeout(() = { const result = doSomeComputation(event.data.data); // Send the result back to the main thread. self.postMessage({ action: 'result', data: result }); }, 0); }});

    Sea consciente del uso de la memoria

    Web Workers tiene su propio espacio de memoria, que puede limitarse según el dispositivo del usuario y la configuración del navegador. Para evitar problemas de memoria, debe tener en cuenta la cantidad de memoria que utiliza su código de Web Worker y evitar crear objetos grandes innecesariamente. Por ejemplo:

    // In the workerself.addEventListener('message', (event) = { if (event.data.action === 'start') { // Use a for loop to process an array of data. const data = event.data.data; const result = []; for (let i = 0; i data.length; i++) { // Process each item in the array and add the result to the result array. const itemResult = processItem(data[i]); result.push(itemResult); } // Send the result back to the main thread. self.postMessage({ action: 'result', data: result }); }});

    En este código, Web Worker procesa una matriz de datos y devuelve el resultado al hilo principal utilizando el postMessagemétodo. Sin embargo, el forbucle utilizado para procesar los datos puede llevar mucho tiempo.

    La razón de esto es que el código procesa una serie completa de datos a la vez, lo que significa que todos los datos deben cargarse en la memoria al mismo tiempo. Si el conjunto de datos es muy grande, esto puede hacer que Web Worker consuma una cantidad significativa de memoria, excediendo potencialmente el límite de memoria asignado al Web Worker por el navegador.

     

    Para mitigar este problema, puede considerar el uso de métodos JavaScript integrados como forEacho reduce, que pueden procesar datos un elemento a la vez y evitar la necesidad de cargar toda la matriz en la memoria a la vez.

    Compatibilidad del navegador

    Web Workers son compatibles con la mayoría de los navegadores modernos, pero es posible que algunos navegadores más antiguos no los admitan. Para garantizar la compatibilidad con una amplia gama de navegadores, debe probar su código de Web Worker en diferentes navegadores y versiones. También puedes usar la detección de funciones para verificar si los Web Workers son compatibles antes de usarlos en tu código, así:

    if (typeof Worker !== 'undefined') { // Web Workers are supported. const worker = new Worker('worker.js');} else { // Web Workers are not supported. console.log('Web Workers are not supported in this browser.');}

    Este código comprueba si los Web Workers son compatibles con el navegador actual y crea un nuevo Web Worker si son compatibles. Si los Web Workers no son compatibles, el código registra un mensaje en la consola que indica que los Web Workers no son compatibles con el navegador.

    Si sigue estas estrategias, puede asegurarse de que su código de Web Worker sea eficiente, receptivo y compatible con una amplia gama de navegadores.

    Conclusión

    A medida que las aplicaciones web se vuelven cada vez más complejas y exigentes, es probable que aumente la importancia de técnicas eficientes de subprocesos múltiples, como los Web Workers. Los Web Workers son una característica esencial del desarrollo web moderno que permite a los desarrolladores descargar tareas que requieren un uso intensivo de la CPU en subprocesos separados, lo que mejora el rendimiento y la capacidad de respuesta de las aplicaciones. Sin embargo, existen limitaciones y consideraciones importantes que se deben tener en cuenta al trabajar con Web Workers, como la falta de acceso al DOM y limitaciones en los tipos de datos que se pueden pasar entre subprocesos.

    Para mitigar estos posibles problemas, los desarrolladores pueden seguir las estrategias mencionadas anteriormente, como utilizar métodos asincrónicos y ser conscientes de la complejidad de la tarea que se descarga.

    Es probable que el multiproceso con Web Workers siga siendo una técnica importante para mejorar el rendimiento y la capacidad de respuesta de las aplicaciones web en el futuro. Si bien existen otras técnicas para lograr subprocesos múltiples en JavaScript, como el uso de WebSockets o SharedArrayBufferWeb Workers, los Web Workers tienen varias ventajas que los convierten en una herramienta poderosa para los desarrolladores.

    La adopción de tecnología más reciente, como WebAssembly, puede abrir nuevas oportunidades para utilizar Web Workers para descargar tareas aún más complejas y con un uso intensivo de computación. En general, es probable que los Web Workers sigan evolucionando y mejorando en los próximos años, ayudando a los desarrolladores a crear aplicaciones web más eficientes y con capacidad de respuesta.

    Además, existen muchas bibliotecas y herramientas para ayudar a los desarrolladores a trabajar con Web Workers. Por ejemplo, Comlink y Workerize proporcionan una API simplificada para comunicarse con Web Workers. Estas bibliotecas abstraen parte de la complejidad de administrar Web Workers, lo que facilita el aprovechamiento de sus beneficios.

    Con suerte, este artículo le ha brindado una buena comprensión del potencial de los trabajadores web para subprocesos múltiples y cómo usarlos en su propio código.

    (gg, yk, il)Explora más en

    • Actuación
    • javascript
    • Herramientas
    • Aplicaciones





    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Explorando el potencial de los trabajadores web para subprocesos múltiples en la Web

    Explorando el potencial de los trabajadores web para subprocesos múltiples en la Web

    SmashingConf Freiburg 2024 Deploy Fast. Deploy Smart Índice Importancia y beneficios de los trabajadores

    programar

    es

    https://aprendeprogramando.es/static/images/programar-explorando-el-potencial-de-los-trabajadores-web-para-subprocesos-multiples-en-la-web-1171-0.jpg

    2024-04-04

     

    Explorando el potencial de los trabajadores web para subprocesos múltiples en la Web
    Explorando el potencial de los trabajadores web para subprocesos múltiples en la Web

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Top 20