这章我们讲回调,英文名:Beyond callbacks

一、章节覆盖:

回调函数及其限制,如网关/边缘服务示例所示
未来和承诺——链接异步操作的简单模型
响应式扩展——一个更强大的模型,特别适合组合异步事件流
Kotlin协程——对异步代码执行流的语言级支持

二、Vert.x中的回调函数是一种非阻塞的异步编程模式,用于处理异步操作的结果。在Vert.x中,回调函数通常用于处理事件,如HTTP请求和数据库查询等,其限制包括:

  1. 回调函数是非阻塞的,不能使用同步代码块或阻塞I/O操作。

  2. 回调函数的执行顺序不可预测,因为它们是异步执行的。

  3. 回调函数需要明确处理错误,不能简单地忽略异常或错误。

  4. 回调函数应该尽量轻量级,避免太复杂的逻辑和操作,以免影响整个应用程序的性能。

  5. 回调函数应该采用良好的编程约定,如命名规范和注释,以便于维护和管理。

回调地狱是指使用嵌套回调来链接异步操作,由于嵌套很深,导致代码更难以理解。对于嵌套回调,错误处理尤其困难。
虽然这是真的,但是可以很容易地为每个异步操作回调使用一个方法来缓解回调地狱,就像我们使用handleRequest、sendToSnapshot和sendResponse方法一样。每个方法只做一件事,我们避免嵌套回调。

二、Futures and promises in Vert.x

类似于:

package furtueAndprimise;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise; public class Test extends AbstractVerticle {
@Override
public void start(Promise<Void> startPromise) throws Exception {
Promise<String> promise=Promise.promise();
vertx.setTimer(5000,id->{
if (System.currentTimeMillis()%2L==0L)
promise.complete("ok");
else
promise.fail(new RuntimeException("Bad luck....")); });
}
}

这里的异步操作是一个5秒的计时器,之后承诺就完成了。根据当前时间是奇数还是偶数,承诺以一个值完成或以一个异常失败。这很好,但我们如何从承诺中获得价值呢?
想要在结果可用时做出反应的代码需要一个future对象。

完整代码:

package furtueAndprimise;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.Vertx; public class Test extends AbstractVerticle {
@Override
public void start(Promise<Void> startPromise) throws Exception {
Promise<String> promise=Promise.promise();
vertx.setTimer(5000,id->{
if (System.currentTimeMillis()%2L==0L)
promise.complete("ok");
else
promise.fail(new RuntimeException("Bad luck....")); });
Future<String> future = promise.future();
future.onSuccess(System.out::println)
.onFailure(err -> System.out.println(err.getMessage())); } public static void main(String[] args) {
Vertx vertx1=Vertx.vertx();
vertx1.deployVerticle(new Test());
}
}

用未来的方法启动HTTP服务器:

package furtueAndprimise;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Handler;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.impl.Http1xServerRequestHandler; public class Test001 extends AbstractVerticle {
@Override
public void start(Promise<Void> promise) {
vertx.createHttpServer()
.requestHandler(requestHandler())
.listen(8080)
.onFailure(fail->{
promise.fail("失败");
})
.onSuccess(ok -> {
System.out.println("http://localhost:8080/");
promise.complete();
});
} Handler<HttpServerRequest> requestHandler(){
return request -> {
// 处理HTTP请求的逻辑
// ...
};
} public static void main(String[] args) {
Vertx vertx1 = Vertx.vertx();
vertx1.deployVerticle(new Test001()); }
}

与CompletionStage api的互操作性:

package furtueAndprimise;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise; import java.util.concurrent.CompletionStage; public class Test002 extends AbstractVerticle {
@Override
public void start() throws Exception {
Promise<String> promise=Promise.promise();
CompletionStage<String> cs = promise.future().toCompletionStage();
cs
.thenApply(String::toUpperCase)
.thenApply(str -> "~~~ " + str)
.whenComplete((str, err) -> {
if (err == null) {
System.out.println(str);
} else {
System.out.println("Oh... " + err.getMessage());
}
});
}
}

CompositeFuture 是一种特殊的 Future,它可以包装一个 Future 列表,从而让一组异步操作并行执行;然后协调这一组操作的结果,作为 CompositeFuture 的结果

三、接下来讲响应式的扩展:

ReactiveX计划为后端和前端项目提供了一个通用的API和多种语言的实现(http://reactivex.io/)。RxJS项目为浏览器中的JavaScript应用程序提供响应式扩展,而像RxJava这样的项目则为Java生态系统提供通用的响应式扩展实现。
vertx提供了RxJava版本1和2的绑定。建议使用版本2,因为它支持背压,而版本1不支持。

单纯讲rxjava,rxjava的五种观察源:

你有时可能会读到热源和冷源。热点源是无论是否存在订阅者都要发出事件的源。冷源是在第一次订阅后才开始发出事件的源。周期计时器是热源,而要读取的文件是冷源。使用冷源,您可以获得所有事件,但使用热源,您只能获得订阅后发出的事件

四、rxjava在vertx里面集成

1.引入依赖

implementation("io.vertx:vertx-rx-java2:version")

package furtueAndprimise;

import io.reactivex.Completable;
import io.reactivex.Observable;
import io.vertx.reactivex.core.AbstractVerticle;
import io.vertx.reactivex.core.RxHelper; import java.util.concurrent.TimeUnit; public class Test003 extends AbstractVerticle {
@Override
public Completable rxStart() {
Observable
.interval(1, TimeUnit.SECONDS, RxHelper.scheduler(vertx))
.subscribe(n -> System.out.println("tick"));
return vertx.createHttpServer()
.requestHandler(r -> r.response().end("Ok"))
.rxListen(8080)
.ignoreElement();
}
}

rxStart使用Completable而不是Future来通知部署成功。通过 ignoreElement()方法 返回一个Completable。这个例子打开一个经典的HTTP服务器,对任何请求都回复Ok。有趣的部分是AbstractVerticle的RxJava变体具有通知部署成功的rxStart(和rxStop)方法。在我们的示例中,当HTTP服务器启动时,垂直已经成功部署,因此我们返回一个Completable对象。
您可以检查前缀为rx的方法是否与为支持RxJava而生成的方法相对应。如果您检查RxJava api,您将注意到原始方法(包括回调)仍然存在。

这个例子中另一个有趣的部分是每秒发出事件的可观察对象。它本质上表现为一个Vert.X定时器可以。RxJava api中有几个操作符方法接受调度器对象,因为它们需要延迟异步任务。默认情况下,它们从自己管理的内部工作线程池回调,这就打破了vertx线程模型假设。我们总是可以经过vertx调度器,以确保事件仍在原始上下文事件循环中被回调。

五、Kotlin coroutines

引入依赖

plugins {
kotlin("jvm") version "kotlinVersion"
}
dependencies {
// (...)
implementation("io.vertx:vertx-lang-kotlin:${vertxVersion}")
implementation("io.vertx:vertx-lang-kotlin-coroutines:${vertxVersion}")
implementation(kotlin("stdlib-jdk8"))
}

一直都在讲vertx,所以Kotlin coroutines没有怎么讲,算了,我还是搞一个例子吧

import kotlin.coroutines.*;
suspend fun hello():String{
delay(1000)
return "Hello!"
} fun main(){
runBlocking{
println(hello()) //这个runBlocking 会一直等协程完成
}

注:这个系列的截图一直都是vertx in Action 那本英文书里面的。。

vertx学习总结5之回调函数及其限制,如网关/边缘服务示例所示未来和承诺——链接异步操作的简单模型响应式扩展——一个更强大的模型,特别适合组合异步事件流Kotlin协程的更多相关文章

  1. Python并发编程06 /阻塞、异步调用/同步调用、异步回调函数、线程queue、事件event、协程

    Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件event.协程 目录 Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件 ...

  2. rxjava回调地狱-kotlin协程来帮忙

    本文探讨的是在tomcat服务端接口编程中, 异步servlet场景下( 参考我另外一个文章),用rxjava来改造接口为全流程异步方式 好处不用说 tomcat的worker线程利用率大幅提高,接口 ...

  3. Kotlin 协程一 —— 全面了解 Kotlin 协程

    一.协程的一些前置知识 1.1 进程和线程 1.1.1基本定义 1.1.2为什么要有线程 1.1.3 进程与线程的区别 1.2 协作式与抢占式 1.2.1 协作式 1.2.2 抢占式 1.3 协程 二 ...

  4. 异步等待的 Python 协程

    现在 Python 已经支持用协程进行异步处理.但最近有建议称添加协程以全面完善 Python 的语言结构,而不是像现在这样把他们作为生成器的一个类型.此外,两个新的关键字---异步(async)和等 ...

  5. Kotlin协程解析系列(上):协程调度与挂起

    vivo 互联网客户端团队- Ruan Wen 本文是Kotlin协程解析系列文章的开篇,主要介绍Kotlin协程的创建.协程调度与协程挂起相关的内容 一.协程引入 Kotlin 中引入 Corout ...

  6. PHP下的异步尝试三:协程的PHP版thunkify自动执行器

    PHP下的异步尝试系列 如果你还不太了解PHP下的生成器和协程,你可以根据下面目录翻阅 PHP下的异步尝试一:初识生成器 PHP下的异步尝试二:初识协程 PHP下的异步尝试三:协程的PHP版thunk ...

  7. Retrofit使用Kotlin协程发送请求

    Retrofit2.6开始增加了对Kotlin协程的支持,可以通过suspend函数进行异步调用.本文简单介绍一下Retrofit中协程的使用 导入依赖 app的build文件中加入: impleme ...

  8. Android Kotlin协程入门

    Android官方推荐使用协程来处理异步问题.以下是协程的特点: 轻量:单个线程上可运行多个协程.协程支持挂起,不会使正在运行协程的线程阻塞.挂起比阻塞节省内存,且支持多个并行操作. 内存泄漏更少:使 ...

  9. 异步时代-java的协程路在何方

    面试官:你知道协程吗? 你:订机票的那个吗,我常用. 面试官:行,你先回去吧,到时候电话联系 ........ 很尴尬,但是事实是,很大一部分的程序员不知道协程是啥玩意,更大一部分的程序员,项目中没用 ...

  10. Kotlin协程第一个示例剖析及Kotlin线程使用技巧

    Kotlin协程第一个示例剖析: 上一次https://www.cnblogs.com/webor2006/p/11712521.html已经对Kotlin中的协程有了理论化的了解了,这次则用代码来直 ...

随机推荐

  1. Stable Diffusion基础:ControlNet之图片风格迁移

    今天继续给大家分享AI绘画中 ControlNet 的强大功能,本次的主角是 Reference,它可以将参照图片的风格迁移到新生成的图片中,这句话理解起来很困难,我们将通过几个实例来加深体会,比如照 ...

  2. QA||TypeError: ‘module‘ object is not callable报错怎么debugIHRM接口自动化测试

    unittest.py生成测试报告时执行报错:TypeError: 'module' object is not callable 代码如下 原因:结合pycharm自动标注和报错信息,分析出应该是H ...

  3. QA|20211013|SecureCRT:如图,有很多^,中文显示有问题,乱码,如何解决

    Q1:如图,有很多^,中文显示有问题,乱码,如何解决 Q2:securecrt的vi展示有问题:少很多字.有很多^M和^,光标无法移动到最右侧 A: 首先检查当前编码格式: 1 echo $LANG ...

  4. [htmlayout] picture标签替代img, 解决更新图片数据后依然显示原图片数据

    在hl中, 你可能遇到过这样的情况.   给img标签设置了一个图片路径.   在软件使用过程中对这个路径的数据进行过重写, 删除等等 但img依然还是显示最初载入的图片数据. 解决办法: 用&quo ...

  5. 【译】在 Visual Studio 2022 中安全地在 HTTP 请求中使用机密

    在 Visual Studio 2022 的17.8 Preview 1版本中,我们更新了 HTTP 文件编辑器,使您能够外部化变量,从而使跨不同环境的 Web API 测试更容易.此更新还包括以安全 ...

  6. KRPano多屏互动原理

    KRPano可以实现多个屏幕之间的同步显示,主要应用到Websocket技术进行通信. 在控制端,我们需要发送当前KRPano场景的实时的视角和场景信息,可以使用如下的代码: embedpano({ ...

  7. mysql触发器使用教程-六种触发器

    参考:https://zhuanlan.zhihu.com/p/439273702 触发器(Trigger)是 MySQL 中非常实用的一个功能,它可以在操作者对表进行「增删改」 之前(或之后)被触发 ...

  8. Solution -「香港网络赛 2016」A+B Problem

    Description Link. 给出一个长度为 \(n\) 的序列 \(a\),问有序三元组 \((a_{i},a_{j},a_{k})\) 使得 \(i\neq j\neq k\) 且 \(a_ ...

  9. Linux 安装 helm

    下载helm压缩包,地址   https://github.com/helm/helm/releases/tag/v3.10.1 选择适合自己操作系统的包 上传解压安装 1 root@calico-m ...

  10. 简化 Go 开发:使用强大的工具提高生产力

    作为 Go 开发人员,应该都知道维持简洁高效开发工作流程的重要性.为了提高工作效率和代码质量,简化开发流程并自动执行重复性任务至关重要.在本文中,我们将探讨一些强大的工具和技术,它们将简化 Go 开发 ...