关于创建相互依赖的异步调用的建议

Posted

技术标签:

【中文标题】关于创建相互依赖的异步调用的建议【英文标题】:Advice on creating asynchronous calls that depend on each other 【发布时间】:2016-05-12 23:11:08 【问题描述】:

我正在尝试创建一个库来对 Web 应用程序进行 API 调用(jira,如果你想知道的话)我的 api 调用工作没有问题,但我希望使代码更具可读性和使用-有能力的。我已经尝试搜索我的需求,但结果我不确定我需要搜索什么。

我遇到了相互依赖的异步调用的问题,我知道我必须等到运行回调才能运行我的下一个项目,但我不确定设计它的最佳方法。

我真的很想将链接作为我的 api 的一个功能,我希望它看起来像这样:

createProject(jsonProjectStuff)
  .setLeadUser("myusername")
  .createBoard("boardName")
     .setBoardPermissions(boardPermissionJSONvar)
  .addRole(personRoleJSONvar);

在这个例子中,一切都必须等待createProject,因为它将返回项目。 createBoard 通常不依赖于项目,但在这种情况下使用它应该“分配”给所做的项目,设置董事会权限仅依赖于 createBoard 工作。 addRole 再次特定于项目。

我的问题是:

    是否可以像这样切换上下文并在它们之间保留数据,而无需从硬编码的响应中运行函数? 如果这是可能的,这是个好主意吗?如果不是,我愿意接受其他计划。

我可以想出几种让它工作的方法,包括使用依赖树注册函数调用,然后在我们进行时履行承诺,尽管此时这对我来说主要是概念性的,因为我正在努力决定最好的.

2016 年 2 月 19 日编辑

因此,我对此进行了更多研究,并决定仅在创建新项目与父项不直接相关时才使用选择性“then”。

//Numbers are ID, string is Name
copyProject(IDorName)
  .setRoles(JSONItem)
  .setOwner("Project.Owner")
  .setDefaultEmail("noreply@fake.com")
  .then(
     copyBoard(IDorName)
       .setName("Blah blah Name project.key"),

     saveFilterAs(IDorName, "Board project.key", 
                  "project = project.key ORDER BY Rank ASC")
       .setFilterPermissions(shareValuesJSON)
   )

我非常喜欢这个解决方案,我唯一不知道该怎么做的是字符串“变量”,我想它可能是"Blah blah Name " + this.project.key 无论哪种方式,我都不确定如何通过“then”函数让copyBoardsaveFilterAs 访问它。

有什么想法吗?

【问题讨论】:

这似乎是个好主意...您可以存储最后一个promise,并且对于每个调用的函数,您可以链接到最后一个promise,并更新最后一个promise变量。 @JoaozitoPolo 在调用需要第一次调用中的变量的深度 4 函数的上下文中,这将如何工作,您介意展示一个简单的示例,以便我可以修改并将其用于我的需要吗? 相关:Combining promises and chaining。从本质上讲,javascript 足够灵活,可以支持您想象的任何异步流畅模式,但它们不一定具有高性能或易于实现。 我们仍在使用事件系统,但我期待反应式编程检查 github.com/ReactiveX/rxandroid/wiki 在那里您可以观察和订阅 @Krum110487:给定箭头函数,上下文并不是什么问题。一般来说,我认为让实例的状态与承诺相关联是一个坏主意,而不是为具有明确定义的状态的实例做出承诺(另见here)。当然,这对实例上的方法链接是有害的;尽管如此,如果你坚持使用流畅的接口,你不应该放弃这个原则——而是围绕实例的 Promise 构建第二个类,并为其提供可链接的方法。 【参考方案1】:

我最近一直在使用 Nightmare(无头浏览器)。

它有一个流畅的 API,使用了很好的设计模式。

调用 API 不会直接执行操作,它只会将它们排队,当您准备好执行时,您必须调用返回承诺的 end 函数。当队列完成异步执行时,promise 就被解决了。

比如你的情况

createProject(jsonProjectStuff)
    .setLeadUser("myusername")
    .createBoard("boardName")
    .setBoardPermissions(boardPermissionJSONvar)
    .addRole(personRoleJSONvar)
    .end() // Execute the queue of operations.
    .then() => 
        // All operations completed.
    ))
    .catch(err => 
        // An error occurred.
    );

我觉得这种模式很优雅。它允许您拥有一个流畅的 API 来构建一系列操作。然后,当您准备好执行上述操作时,您调用end(或其他)。然后异步完成操作序列,并使用 Promise 处理完成和错误。

【讨论】:

以上是关于关于创建相互依赖的异步调用的建议的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot之@Async异步调用

接口异步调用,接口耗时减少的可不是一点点

学习RxJS: 导入

将同步 qtdbus 调用转换为异步所需的设计建议

从 Task.WhenAll 调用的异步方法使用 DbContext 并返回错误

nodejs-在函数内执行多个异步调用的最佳方法?