Cómo verificar si ya hay una función en ejecución y si existe escuchar el resultado de esta función;
async function a() { // wait 5 seconds and return foo = foo + 1; // if A is already running await and return result of this running function A instead result; }Si traduzco el problema correctamente, A devuelve una promesa que se liquida de forma asíncrona. Mientras la promesa está pendiente, todas las llamadas a una función contenedora alrededor de A deberían devolver la promesa pendiente actualmente.
Sin embargo, si A no ha sido llamado, o se ha cumplido una promesa de devolución anterior, A debe ser llamado nuevamente.
Esto se puede lograr encadenando la promesa devuelta por A, utilizando controladores de promesa para determinar que los resultados ya no están pendientes y haciendo que la función contenedora devuelva la promesa encadenada. Este código de ejemplo acelera un poco el proceso: cuatro llamadas sucesivas realizadas con a diferencia de 500 ms obtienen el mismo valor cumplido de A , que tarda 2000 ms en realizar una tarea asincrónica mítica:
// promise a delay const delay = ms => new Promise(resolve=>setTimeout(resolve, ms)); // async function A let foo =0; async function A() { await delay( 2000); // 2 second example return foo = foo + 1; } // Wrapper function a const a=(()=>{ let pending = null; const onfulfill = data => { pending = null; return data}; const onreject = err => { pending = null; throw err}; let a = ()=> pending || (pending = A().then(onfulfill, onreject)); return a; })(); // and test async function test() { for( let i=1; i < 11; ++i) { a().then( data=> console.log(`a() call ${i} fulfills with ${data}`)); await delay(500); } } console.log(" a is a named function ", a.name == 'a') test();a está codificado para ser una función con nombre que minimiza la creación de objetos en tiempo de ejecución utilizando la forma de dos parámetros de then y pasando funciones precompiladas como argumentos de controlador.a valor prometido pendiente a cambio.Solución
Puede crear una clase que ejecutará un flujo (máximo) y esperará el resultado si el flujo ya se está ejecutando. Puede verse algo así:
class OneThreadExecutor { // Boolean variable which represents is task running right now taskRunning = false; // All Promise.resolve callbacks listeners = []; // Accept initial value constructor(value = 0) { this.value = value; } // Send [result = value + 1] after 5 sec startNewTask = () => { this.taskRunning = true; setTimeout(() => { this.taskRunning = false; return this.sendResult(); }, 5000) } // Call all Promise.resolve callbacks, and pass [value + 1] to them sendResult = () => { for (const listener of this.listeners) { listener(++this.value); } this.listeners = []; } // Main method that exec one task getResult = () => new Promise(resolve => { // Add callback to queue this.listeners.push(resolve); // Start new task if necessary if (!this.taskRunning) this.startNewTask(); }) } Concepto general
El método Async getResult registrará la promesa en la cola de la clase. Cualquier ejecución exitosa de la tarea enviará el resultado a la cola. La tarea actual devuelve el value + 1 en cada llamada a getResult y toma 5 segundos para el flujo completo.
Uso
const a = new OneThreadExecutor(); // value = 0 by default // will start task#1, 5 sec left till .then call, value = 1 a.getResult().then(...) // 2.5 sec left, task#1 is already half progress, value = 2 setTimeout(() => { a.getResult().then(...) }, 2500)asíncrono/espera
const a = new OneThreadExecutor(3); // let's set value = 3 initially // will start task#1, 5 sec left till .then call, value = 4 a.getResult(); // wait till task#1 completed, 5 sec left, value = 5 const value = await a.getResult(); // will start task#2 bacause not task running, 5 sec left, value = 6 a.getResult(); Contras
En la solución de demostración, ya esperamos una ejecución exitosa de la tarea, sin manejo de errores, por lo que es posible que deba ampliarla para detectar errores correctamente durante la ejecución de la tarea.
var is_a_running = false; function a() { if (is_a_running == false) { is_a_running = true //do something //after you have done the thing is_a_running = false } else if (is_a_running == true){ result(); } }Esto debería ayudarte