Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

91
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda