专业的编程技术博客社区

网站首页 > 博客文章 正文

JavaScript Promise实现任务的灵活调度

baijin 2024-10-11 10:47:06 博客文章 13 ℃ 0 评论

前言

JavaScript中的Promise有助于处理许多异步任务。标准函数Promise.prototype.then()和Promise.all()分别用于顺序和并行执行的调度任务。

然而,假设我们要执行许多异步任务,其中一些任务取决于其他任务。在这种情况下,Promise.all()不会因为相互依赖关系而工作,而Promise.prototype.then()将非常低效,因为在不必要的时候,我们将依次执行任务。

在本文中,将提出了一个简单的函数,处理一个相互依赖的JavaScript承诺网络的最佳调度的一般情况(即异步任务的有向非循环图和它们之间的依赖关系)。

Promise.prototype.then和Promise.all

JavaScript语言提供了将多个异步任务组合到一个Promise中的内置机制。我们讨论其中两个。

Promise.prototype.then()

也许最重要的组合Promise的方法是使用 Promise.prototype.then()。它允许一个Promise链接到另一个Promise,以便顺序执行两个异步任务。

我们也可以用then(),来形成更长的顺序执行的异步任务链。一个then()的输出将作为下一个then()的输入。这是一个Promise链接的例子:

这段代码通过Promise.prototype.then()实现的任务如下图:

Promise.all()

Promise.all()是另一种结合Promise的方法。它允许从列表(好的,可迭代的)的Promise中创建一个Promise。

  • 一旦提供的Promise被拒绝,就会被拒绝,

  • 当所有的Promise被分解时,Promise.all()将被分解。

特别地,所有提供的承诺代表并行运行的任务。以下是使用以下示例 Promise.all():

上图代码实现的功能如下图:

泛化:任务的有向非循环图

我们在这篇文章中写的功能泛化了Promise(使用 Promise.prototype.then() )和同时执行Promise(使用 Promise.all() )。它允许有效地执行任务网络,或者如果需要,任务的依赖图。换句话说,我们正在写的功能适合于上述情况,也适用于这种情况:

函数参数

我们将调用函数 promiseDAG() (DAG代表有向非循环图)。它将如下所示:

提供的参数是:

  • callbacks:函数列表,每个函数都返回一个promise,当被调用时,这些是我们要执行的异步任务,它们是有向无环图中的节点。

  • dag:列表列表,指定任务之间的相互依赖关系指定有向无环图中的边(并确定哪些参数将提供给回调)。

如果提供了n个回调,则 dag 应该是 n 个整数列表的列表。在第 i 个进行回调。例如,如果dag[i]包含整数 j,则有向无环图具有从第j个任务到第i个任务的边。

上面显示的网络是通过执行以下操作来执行的:

功能行为

什么时候 promiseDAG() 被调用,任何没有进入的任务(即不依赖于其他任务)都将启动。每当任务完成时,完成所有必备条件的任务即将开始。提供给回调的参数正是其先决条件解析的值,顺序与它们所指定的顺序相同dag。

注意: 当JavaScript函数被调用的参数多于接受的值时,多余的参数被默认忽略。这意味着如果taskB依赖于taskA,但不需要知道taskA解析的值,则可以在有向无环图中指示依赖关系,但将taskB()函数作为函数无参数。

当所有任务成功完成后,promise将通过promiseDAG()得到解析值。返回的promise的callbacks值是与所有已解决的任务promise的返回值相同的长度的列表。

一旦任何一个任务失败,返回的promise就被promiseDAG()拒绝,相同地错误将与失败的任务被拒绝。没有任何新任务将会被启动(尽管目前运行的任务将继续运行,因为无法取消等待的promise)。

promiseDAG函数

我们来看看内部的内容 promiseDAG()。该功能的结构如下:

该函数handleResolution()将注册一个promise解析值,并启动任何现在有其先决条件满足的承诺(除非promise早先已经被拒绝,在这种情况下不会启动新的任务)。

该函数handleRejection()将简单地拒绝所构造的promise,未经修改地promiseDAG()传递错误。

示例

假设您正在运行一个具有当天视频的网站。当用户访问该站点时,需要执行以下操作:

  1. 登录用户

  2. 取出用户的设置

  3. 将用户的设置解析为JSON

  4. 加载当天的视频(仅适用于注册用户)

  5. 根据用户的设置更改页面的背景颜色

  6. 播放视频,如果用户已启用自动播放

任务及其相互依存关系如下所示:

实现上图的代码如下:

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表