vertx学习总结5

news2024/11/18 9:41:21

这章我们讲回调,英文名: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 那本英文书里面的。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1059870.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

408-2013

一、单项选择题&#xff08;2分/题&#xff09; 1.已知两个长度分别为 m 和 n 的升序链表&#xff0c;若将他们合并为一个长度为 mn 的降序链表&#xff0c;则最坏情况下的时间复杂度为______。 A.O(n) B.O(mn) C.O(min(m,n)) D.O(max(m,n)) 解答&#xf…

【算法|动态规划No.10】leetcode LCR 089. 打家劫舍 LCR 090. 打家劫舍 II

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

Android---GC回收机制与分代回收策略

目录 GC 回收机制 垃圾回收(Garbage Collection, GC) 垃圾回收算法 JVM 分代回收策略 1. 新生代 2. 老年代 GC Log 分析 引用 GC 回收机制 垃圾回收(Garbage Collection, GC) 垃圾就是内存中已经没有用的对象&#xff0c;JVM 中的垃圾回收器(Garbage Collector)会自…

【Unity】两种方式实现弹跳平台/反弹玩家(玩家触发与物体自身触发事件实现蹦床的物理效果)

一、声明 只实现物理反弹的效果&#xff0c;不实现蹦床会有的视觉拉伸效果&#xff0c;请自行找相关代码 二、实现 经过我的实践&#xff0c;我发现要想实现一个平台反弹的效果&#xff0c;要么就选择给player添加一个物理材质&#xff08;平台加了没用&#xff09;&#xff0…

【网络】网络扫盲篇 ——用简单语言和图解带你入门网络

网络的一些名词和基础知识讲解 前言正式开始一些基础知识发展背景运营商和生产商 协议协议的分层TCP/IP五层(或四层)模型&#xff08;可以不看&#xff0c;对新手来说太痛苦了&#xff0c;我这里只是为了让屏幕前的你过一遍就好&#xff0c;里面很多概念新手是不太懂的&#xf…

【多线程】进程与线程 并发编程 面试题总结

进程和线程 进程是程序执行时的一个实例&#xff0c;即它是程序已经执行到何种程度的数据结构的汇集。从内核的观点看&#xff0c;进程的目的就是担当分配系统资源&#xff08;CPU时间、内存等&#xff09;的基本单位。线程是进程的一个执行流&#xff0c;是CPU调度和分派的基…

postgresql16-新特性

postgresql16-新特性 any_value数组抽样数组排序 any_value any_value 返回任意一个值 select e.department_id ,count(*), any_value(e.last_name) from cps.public.employees e group by e.department_id ;数组抽样 -- 从数组中随机抽取一个元素 array_sample(数组&#…

java的内存模型(概念)

在java中&#xff0c;设计之初就有了&#xff1a;主内存、线程工作内存&#xff0c;所以其实每一个线程执行时&#xff0c;都是将主线程copy一份到工作线程&#xff0c;执行修改后&#xff0c;再同步回去。 所以&#xff0c;就有四组内存操作方式&#xff1a; 1、读主内存&…

【python】数据加载与存储

文章目录 读取文本格式的数据逐块读取文本文件将数据写出到文本格式 读取文本格式的数据 pandas提供了一些用于将表格型数据读取为DataFrame对象的函数&#xff1a; 【read_csv和read_table最为重要】 这些函数在将文本数据转换为DataFrame时所用到的一些技术。这些函数的选项…

C++:stl:stack、queue、priority_queuej介绍及模拟实现和容量适配器deque介绍。

本文主要介绍c中stl的栈、队列和优先级队列并对其模拟实现&#xff0c;对deque进行一定介绍并在栈和队列的模拟实现中使用。 目录 一、stack的介绍和使用 1.stack的介绍 2.stack的使用 3.stack的模拟实现 二、queue的介绍和使用 1.queue的介绍 2.queue的使用 3.queue的…

Vue中如何进行分布式路由配置与管理

Vue中的分布式路由配置与管理 随着现代Web应用程序的复杂性不断增加&#xff0c;分布式路由配置和管理成为了一个重要的主题。Vue.js作为一种流行的前端框架&#xff0c;提供了多种方法来管理Vue应用程序的路由。本文将深入探讨在Vue中如何进行分布式路由配置与管理&#xff0…

【kubernetes】kubernetes中的Controller

1 什么是Controller&#xff1f; kubernetes采用了声明式API&#xff0c;与声明式API相对应的是命令式API&#xff1a; 声明式API&#xff1a;用户只需要告诉期望达到的结果&#xff0c;系统自动去完成用户的期望命令式API&#xff1a;用户需要关注过程&#xff0c;通过命令一…

EdgeView 4 for Mac:重新定义您的图像查看体验

您是否厌倦了那些功能繁杂、操作复杂的图像查看器&#xff1f;您是否渴望一款简单、快速且高效的工具&#xff0c;以便更轻松地浏览和管理您的图像库&#xff1f;如果答案是肯定的&#xff0c;那么EdgeView 4 for Mac将是您的理想之选&#xff01; EdgeView 4是一款专为Mac用户…

【C语言】结构体内存对齐

结构体内存对齐是很重要的一个考点&#xff0c;但不难掌握&#xff0c;接下来就来了解一下结构体内存对齐 目录 对齐规则&#xff1a;偏移量&#xff1a;例题&#xff1a;为什么存在内存对齐? 对齐规则&#xff1a; 首先来看一下对齐规则 第一个成员在与结构体变量偏移量为0…

交叉编译和GCC编译器

目录 交叉编译 hello.c文件 提问 GCC编译器 GCC编译过程 GCC常用选项 编译多个文件 预处理 编译 汇编 链接 交叉编译 hello.c文件 #include <stdio.h>int main(int argc, char argv) {if(argc > 2)printf("Hello, %s!\n", argv[1]);elseprintf…

【Spring Boot】创建一个 Spring Boot 项目

创建一个 Spring Boot 项目 1. 安装插件2. 创建 Spring Boot 项目3. 项目目录介绍和运行注意事项 1. 安装插件 IDEA 中安装 Spring Boot Helper / Spring Assistant / Spring Initializr and Assistant插件才能创建 Spring Boot 项⽬ &#xff08;有时候不用安装&#xff0c;直…

JVM:如何通俗的理解并发的可达性分析

并发的可达性分析 前面在介绍对象是否已死那一节有说到可达性分析算法&#xff0c;它理论上是要求全过程都基于一个能保障一致性的快照&#xff08;类比 MySQL 的MVCC&#xff09;中才能够进行分析&#xff0c;也就意味着必须全程冻结用户线程的运行&#xff08;STW&#xff0…

实战型开发1/3--结果业务导向

假期难得一段时间把近期一些实战型开发的阅读&#xff0c;实践做一些小结&#xff1b; 风格方面就是包括不限于一些好的开发实践&#xff0c;nb的开发技术流程等&#xff0c;但是总体着力于实战型的开发&#xff1b; 三层视角 业务&团队视角&#xff1a;开发所要最终服务…

单调栈---基础数据结构与算法

简介 栈 (stack) 又名堆栈&#xff0c;是一种数据结构&#xff0c;向一个栈插入新元素又称作进栈、入栈或压栈&#xff0c;从一个栈删除元素又称作出栈或退栈。 栈是一种只允许在表尾进行插入和删除操作的线性表&#xff0c;也就是我们所说的后进先出&#xff0c;我们把栈想象…

软件测试工程师经典面试题,金九银十可以跳槽了。

大家好&#xff0c;前两天跟朋友感慨&#xff0c;今年的铜九铁十、裁员、导致好多人都没拿到offer&#xff01;现在互联网大厂终于迎来了应届生集中求职季。 对于想跳槽的职场人来说&#xff0c;绝对是个找工作的好时机。这时候&#xff0c;很多高薪技术岗、管理岗的缺口和市场…