Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

89
Vistas
Task Runner in Javascript

I have a list of tasks and all these tasks need to be executed only after all the dependencies are resolved for each task. I am struggling to figure out a way to finish running all the tasks in optimal time.

// Each node is a async job, illustrated by setTimeout.
// A and C can run at the same time.
// D, needs to wait for A and C to be done.
// E needs to wait for A and D to be done.

function runTasks(tasks) {
 // run tasks
}

// Sample of tasks
var tasks = {
  'a': {
    job: function (finish) {
      setTimeout(function () {
        console.log('a done');
        finish();
      }, 500);
    },
  },
  'c': {
    job: function (finish) {
      setTimeout(function () {
        console.log('c done');
        finish();
      }, 200);
    },
    dependencies: [],
  },
  'd': {
    job: function (finish) {
      setTimeout(function () {
        console.log('d done');
        finish();
      }, 100);
    },
    dependencies: ['a','c'],
  },
  'e': {
    job: function (finish) {
      setTimeout(function () {
        console.log('e done');
        finish();
      }, 200);
    },
    dependencies: ['a', 'd'],
  },
};
about 4 years ago · Juan Pablo Isaza
3 Respuestas
Responde la pregunta

0

Something like this might be possible, I have changed the jobs to async methods and I keep track of them being resolved or not.

This code does not check for errors within the job or for circular dependencies.

Output of the script:

b done
a done
c done
e done
done

Code:

const runTasks = async tasks => {
  const taskArray = Object.entries(tasks)
  const resolved = {}

  while (taskArray.length) {
    const tasksToExecute = []
    for (const task of taskArray) {
      const dependencies = task[1].dependencies || []
      if (dependencies.length === 0 || dependencies.every(dependency => resolved[dependency] || false)) {
        tasksToExecute.push(task)
      }
    }

    await Promise.all(tasksToExecute.map(t => t[1].job()))
    tasksToExecute.forEach(t => {
      resolved[t[0]] = true
      taskArray.splice(taskArray.indexOf(t[0]), 1)
    })
  }
}

const tasks = {
  a: {
    job: async function () {
      return new Promise(resolve => {
        setTimeout(() => {
          console.log("a done")
          resolve()
        }, 500)
      })
    },
  },
  c: {
    job: async function () {
      return new Promise(resolve => {
        setTimeout(() => {
          console.log("c done")
          resolve()
        }, 200)
      })
    },
    dependencies: ["a", "b"],
  },
  b: {
    job: async function () {
      return new Promise(resolve => {
        setTimeout(() => {
          console.log("b done")
          resolve()
        }, 100)
      })
    },
    dependencies: [],
  },
  e: {
    job: async function () {
      return new Promise(resolve => {
        setTimeout(() => {
          console.log("e done")
          resolve()
        }, 200)
      })
    },
    dependencies: ["c", "b"],
  },
}

runTasks(tasks).then(r => console.log("done"))
about 4 years ago · Juan Pablo Isaza Denunciar

0

A simple recursive dependencies evaluation with caching of results will do. Use Promise.all to wait for all dependencies:

function runTasks(tasks) {
  const promises = {};
  function runTask(name) {
    const {dependencies, job} = tasks[name];
    return promises[name] ??= Promise.all(dependencies.map(runTask)).then(job);
  }
  return Promise.all(Object.keys(tasks).map(runTask));
}

Maybe use Promise.allSettled instead of Promise.all in the final return statement.

If you need to detect circular dependencies, you can use

…
  const circular = Promise.reject(new Error("circular dependency"));
  circular.catch(() => { /* ignore */ }); // prevent unhandled rejection
  function runTask(name) {
    const {dependencies, job} = tasks[name];
    if (promises[name] != null) return promises[name];
    promises[name] = circular;
    return promises[name] = Promise.all(dependencies.map(runTask)).then(job);
  }
…
about 4 years ago · Juan Pablo Isaza Denunciar

0

You can start parallel promises which can be started.

  1. Start all independent task first which has no dependencies
  2. After completing independent tasks store in map/set
  3. Then filter a new set of tasks using the complete set repeat steps.

const wait = (ms, task) =>
  new Promise((resolve) =>
    setTimeout(() => {
      console.log(`${task} done`);
      resolve();
    }, ms)
  );

const tasks = {
  a: {
    job: () => wait(500, "A"),
    dependencies: [],
  },
  c: {
    job: () => wait(500, "C"),
    dependencies: [],
  },
  d: {
    job: () => wait(500, "D"),
    dependencies: ["a", "c"],
  },
  e: {
    job: () => wait(500, "E"),
    dependencies: ["a", "d"],
  },
};

const run = async () => {
  const completed = new Set();
  const keys = Object.keys(tasks);
  const runTasks = async (pendingTasks) => {
    const promises = pendingTasks.map((key) => tasks[key].job());
    await Promise.all(promises);
    pendingTasks.forEach((key) => completed.add(key));
  };

  const runner = async () => {
    const pendingTasks = keys.filter((key) => {
      if (!completed.has(key)) {
        const { dependencies } = tasks[key];
        return dependencies.every((dependency) => completed.has(dependency));
      }
      return false;
    });
    if (pendingTasks.length !== 0) {
      await runTasks(pendingTasks);
      return runner();
    }
  };

  await runner();
};

run();

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda