Javascript 如何使一系列任务中的一项等待其他任务完成?

Javascript 如何使一系列任务中的一项等待其他任务完成?,javascript,Javascript,我有一个长长的对象数组,其中包含: 1) 进程的名称(“名称”) 2) 函数(“任务”) 3) 该函数的参数(“参数”) 有些任务依赖于在执行之前完成的其他任务。我希望他们动态地等待任何依赖项的完成 我希望做的是让一个异步函数为依赖于其他部分的函数提供名称参数。以这种方式,函数将一直处于等待状态,直到任务可以执行为止。我需要它是动态的,没有2或3个单独执行的列表。根据其他相关任务的不同,可能存在任务 任务列表: let tasks = [ {name: 'numerator', task

我有一个长长的对象数组,其中包含:

1) 进程的名称(“名称”) 2) 函数(“任务”) 3) 该函数的参数(“参数”)

有些任务依赖于在执行之前完成的其他任务。我希望他们动态地等待任何依赖项的完成

我希望做的是让一个异步函数为依赖于其他部分的函数提供名称参数。以这种方式,函数将一直处于等待状态,直到任务可以执行为止。我需要它是动态的,没有2或3个单独执行的列表。根据其他相关任务的不同,可能存在任务

任务列表:

let tasks = [
    {name: 'numerator', task: insert, arguments: ['part', 'UK', '2010']},
    {name: 'divide', task: calculate, arguments: ['UK', '2010', await waitFor('numerator'), await waitFor('denominator')]},
    {name: 'denominator', task: insert, arguments: ['whole', 'UK', '2010']}
];
循环:

tasks.forEach(d => {
    d.task(d.arguments);
}
职能:

async function waitFor(taskName) {
    await tasks.find(d => d.name === taskName).task;
    return taskName;
}

async function insert(mode, country, year) {
    //Connect to database, sum up raw data and insert
}

async function divide(country, year, upper, lower) {
    //Connect to database, retrieve the values, divide one by the other and insert
}
现在,我非常清楚上述解决方案不起作用。我看到两个问题: 1) waitFor函数在初始化任务数组之前引用该数组 2) 承诺并不像我希望的那样有效。从属任务的执行不会神奇地延迟,直到其他任务完成

有人可能会说这是一种愚蠢的做事方式。我继承了一些代码,其中每个任务都有一个固定的顺序并等待,这非常耗时。我希望创建一个系统,在这个系统中可以添加任务,并自动协调一切。因此,问题是:

waitFor函数应该如何编写,如何在tasks数组中使用它才能工作


非常感谢您的帮助。

我想您正在寻找

const numeratorPromise = insert('part', 'UK', '2010');
const denominatorPromise = insert('whole', 'UK', '2010');
const dividePromise = Promise.all(['UK', '2010', numeratorPromise, demoniatorPromise])
                      .then(args => calculate(...args));

// await dividePromise - or whatever you want to do with the result

您可以以这种方式构建任意多个承诺,对以前创建的承诺具有任意依赖性,并且它们将尽可能并发运行<代码>承诺。所有确保满足依赖关系。那就等着最后的结果吧。

我想你在寻找

const numeratorPromise = insert('part', 'UK', '2010');
const denominatorPromise = insert('whole', 'UK', '2010');
const dividePromise = Promise.all(['UK', '2010', numeratorPromise, demoniatorPromise])
                      .then(args => calculate(...args));

// await dividePromise - or whatever you want to do with the result

您可以以这种方式构建任意多个承诺,对以前创建的承诺具有任意依赖性,并且它们将尽可能并发运行<代码>承诺。所有确保满足依赖关系。然后等待单一的、最终的结果承诺。

我只需要从
waitFor
返回一个承诺,然后在相关任务完成时解决这个问题。评估任务首先等待其所有参数:

 const byName = {};

  let tasks = [
   {name: 'numerator', task: insert, arguments: ['part', 'UK', '2010']},
   {name: 'divide', task: calculate, arguments: ['UK', '2010', waitFor('numerator'), waitFor('denominator')]},
  {name: 'denominator', task: insert, arguments: ['whole', 'UK', '2010']}
 ];


 function waitFor(name) {
   if(byName[name]) {
      return byName[name].done;
   } else {
      const task = byName[name] = { name };
      return task.done = new Promise(resolve => task.resolve =  resolve);         
   }
 }

 function runTask({ name, task, arguments }) {
   waitFor(name); // cause promise to be set up, dont await!

   byName[name].resolve(
    Promise.all(arguments)
      .then(args => task(...args))
   );
 }

 tasks.forEach(runTask);

确保不存在会导致死锁的循环依赖项。

我只需从
waitFor
返回一个承诺,然后在相关任务完成时解决该问题。评估任务首先等待其所有参数:

 const byName = {};

  let tasks = [
   {name: 'numerator', task: insert, arguments: ['part', 'UK', '2010']},
   {name: 'divide', task: calculate, arguments: ['UK', '2010', waitFor('numerator'), waitFor('denominator')]},
  {name: 'denominator', task: insert, arguments: ['whole', 'UK', '2010']}
 ];


 function waitFor(name) {
   if(byName[name]) {
      return byName[name].done;
   } else {
      const task = byName[name] = { name };
      return task.done = new Promise(resolve => task.resolve =  resolve);         
   }
 }

 function runTask({ name, task, arguments }) {
   waitFor(name); // cause promise to be set up, dont await!

   byName[name].resolve(
    Promise.all(arguments)
      .then(args => task(...args))
   );
 }

 tasks.forEach(runTask);

确保不存在会导致死锁的循环依赖项。

它是否一定需要是一个
任务列表
(需要拓扑排序、拒绝无效依赖项等),或者您可以只编写普通代码?@bergi感谢您的时间。我认为任何代码都可以通过自动协调异步执行一系列函数。很抱歉写了“taskList”,这是我代码中数组的实际变量名。这个想法只是为了取代苏联式的排队等待系统,这种系统速度慢且难以维护。那么,您是否需要自动协调,能够等待列表中所列的内容?请参阅我的答案,了解如何优化队列等待代码,在可能的情况下允许并发。顺便说一句,如果你可以发布你的实际代码(不只是三个调用),那么最好进行演示。它是否一定需要是一个
任务列表
(这需要拓扑排序、拒绝无效依赖项等),或者你可以只编写普通代码?@bergi感谢你的时间。我认为任何代码都可以通过自动协调异步执行一系列函数。很抱歉写了“taskList”,这是我代码中数组的实际变量名。这个想法只是为了取代苏联式的排队等待系统,这种系统速度慢且难以维护。那么,您是否需要自动协调,能够等待列表中所列的内容?请参阅我的答案,了解如何优化队列等待代码,在可能的情况下允许并发。顺便说一句,如果你可以发布你的实际代码(不只是三个调用),那么最好演示一下。这要求任务总是在其依赖项之后发生……在OPs代码中不是这样。@Jonaswillms是的,这就是我写“依赖于先前创建的承诺”的原因。但是从“我继承了一段代码,其中每个任务都有一个设置的顺序并等待,这非常耗时”,我判断OP实际上没有一个任意顺序的任务数组,他只是想要一个解决方案,让他同时运行多个事情,并且能够采用顺序。这会起作用,但如果可能的话,我宁愿不处理事情的顺序。顺序是存在的,但维护起来很烦人。@K.Nordqvist好吧,你必须至少处理一点顺序,以避免引入循环依赖。如果您的函数变得难以维护,您可能需要考虑将其重构为可以独立运行的多个较小的部分。@ K.NordQVIST,如果您真的想使用一个可以任意插入计算的数据结构,那么我建议编写一个建立订单的算法。(重要的是,如果你搞砸了,会抛出一个错误——乔纳斯的解决方案在这种情况下会挂起),然后为每个任务建立一个承诺,就像我的回答一样。这要求任务总是在其依赖项之后发生……这在OPs代码中不是这样。@Jonaswillms是的,这就是我写“依赖于先前创建的承诺”的原因但是从“我继承的代码中,每个任务都有一个设置的顺序和等待,这非常耗时”,我判断OP实际上没有一个任意或任意的数组