关于#javascript#的问题,请各位专家解答!异步promise



```html
const sleep = (delay) => new Promise((r) => setTimeout(r, delay))

const tasks = {
  a: {
    job: async function () {
      await sleep(1000)
      console.log('Tasks A running')
    },
    dependency: ['c', 'b'],
  },
  b: {
    job: async function () {
      await sleep(3000)
      console.log('Tasks B running')
    },
    dependency: [],
  },
  c: {
    job: function () {
      console.log('Tasks C running')
    },
    dependency: [],
  },
  d: {
    job: function () {
      console.log('Tasks D running')
    },
    dependency: ['c'],
  },
}

function run(tasks) {
  // ...Write your answer here
  // The params `tasks` can be multiple of task, not just a、b、c、d. so don't answer with `a.job()` etc.
  // Answer should not include keyword of a/b/c/d
}

run(tasks)   


```

可以使用拓扑排序来解决该问题,基本思想是先遍历所有没有依赖关系的任务,再遍历它们的子任务,直到所有任务都被遍历完。

以下是一个基于该思想的实现:

function run(tasks) {
  const taskNames = Object.keys(tasks)
  const taskDepMap = {}
  const taskDepCount = {}
  const result = []

  // 初始化任务依赖关系映射和依赖计数
  taskNames.forEach((name) => {
    const task = tasks[name]
    taskDepMap[name] = task.dependency.slice()

    const count = task.dependency.length
    taskDepCount[name] = count
    if (count === 0) {
      result.push(name)
    }
  })

  // 依次遍历每个任务,并执行
  let i = 0
  while (i < result.length) {
    const name = result[i]
    const task = tasks[name]
    task.job()

    // 更新子任务的依赖计数
    taskDepMap[name].forEach((dep) => {
      taskDepCount[dep]--
      if (taskDepCount[dep] === 0) {
        result.push(dep)
      }
    })

    i++
  }
}

以上代码首先初始化了任务依赖关系和依赖计数,然后按照依赖计数从小到大的顺序依次遍历任务,并执行任务的job()方法。在执行任务的job()方法后,还会更新子任务的依赖计数,并将依赖计数为0的任务添加到结果集中。

这样,就能够保证所有任务都能够按照正确的顺序执行。

-- 本次回答基于 chatgpt3.5