Forest Forest
💒 首页
  • v1.5.30
  • v1.5.28
  • 🎄 ForestX
🌰 案例
💖 支持
🛫 更新记录
🧢 开发团队
⚒️ 参与贡献
  • MaxKey - 业界领先的身份管理和认证产品 (opens new window)
  • Snowy - 国内首个国密前后端分离快速开发平台 (opens new window)
  • Eoapi - 一个开源、可拓展的 API 工具平台 (opens new window)
  • Gitee (opens new window)
  • Github (opens new window)
💒 首页
  • v1.5.30
  • v1.5.28
  • 🎄 ForestX
🌰 案例
💖 支持
🛫 更新记录
🧢 开发团队
⚒️ 参与贡献
  • MaxKey - 业界领先的身份管理和认证产品 (opens new window)
  • Snowy - 国内首个国密前后端分离快速开发平台 (opens new window)
  • Eoapi - 一个开源、可拓展的 API 工具平台 (opens new window)
  • Gitee (opens new window)
  • Github (opens new window)
  • 序言

    • 🎁 新手介绍
    • 📖 文档
    • 🌰 使用案例
    • 🕵️‍ 关于作者
    • 👨‍🎓 贡献者列表
  • 入门

    • 🎬 安装配置说明
    • 🏹 Springboot环境安装
    • 📐 Springboot环境配置
    • 🎯 Springboot环境使用
    • 🏹 Spring环境安装
    • 📐 Spring环境配置
    • 🎯 Spring环境使用
    • 🏹 原生Java环境安装
    • 📐 原生Java环境配置
    • 🎯 原生Java环境使用
    • 🧬 编程式接口
  • 配置项

    • 👜 Springboot环境配置项
    • 👝 Spring环境配置项
    • 🎒 原生Java环境配置项
    • 📚 配置优先级/作用域
  • 声明式接口

    • 🧱 构建接口
    • 🍀 请求方法
    • 🚚 请求地址
    • 🎈 URL 参数
    • 🍭 请求头
    • 👔 请求体
    • 🍮 后端框架
    • 🧁 接口注解
    • 📬 接收数据
    • 🍛 数据转换
    • 🍓 成功/失败条件
    • 🍌 重试机制
    • 🥂 重定向
    • 🍔 Gzip解压
    • 🎂 日志管理
    • ⚽ 回调函数
    • 🍟 异步请求
    • 🛡️ HTTPS
    • 🍪 使用Cookie
    • 🛸 使用代理
    • 🍉 上传下载
    • 🚑 异常处理
  • 编程式接口

    • 请求API

      • 🚀 请求对象
      • 🚢 请求属性
      • ✨ 执行请求
      • 🎊 后端框架
      • 🎪 请求类型
      • 🔮 请求地址
      • 🧀 URL 参数
      • 🚅 请求头
      • 🚋 请求体
      • ⚓ 回调函数
      • 🚁 异步请求
        • 同步/异步
        • 异步和回调函数
        • Async/Await 风格
        • Kotlin 协程
      • 🥯 Cookie
      • 🍜 成功/失败条件
      • 🌶️ 重试机制
      • ⛵ 重定向
      • 🛰️ 请求代理
    • 响应API

      • 🌠 响应对象
      • ✒️ 读取数据
      • 🦋 响应状态码
      • 🏥 响应错误处理
      • 🎧 响应头
      • 🥞 Cookie
  • 模板表达式

    • 🍬 Hello World
    • 🍹 配置属性引用
    • 🍖 变量引用
    • 🥃 动态变量绑定
    • 🥗 参数序号引用
    • 🍍 引用对象属性
    • 🥝 调用对象方法
  • 高级特性

    • 🥪 拦截器
    • 🍏 自定义注解
    • 🍇 组合注解
    • 🥑 自定义转换器
  • v1.5.28文档
  • 编程式接口
  • 请求API
公子骏
2022-07-14
目录

🚁 异步请求

Forest 在默认情况下发送的请求都是同步的,也就是说从发送请求开始,调用发送的线程就会被阻塞,直到请求的响应结果返回之后才会继续往下执行

但同样 Forest 也支持异步请求,允许您异步调用请求接口,而调用接口所在的线程不会被阻塞,可以继续往下做其它事情,这样就不会白白浪费机器的性能

# 同步/异步

Forest请求默认为同步的,可以通过async()方法设置为异步请求

setAsync(boolean async) 设置是否异步

  • 参数aysnc: true 异步, false 同步

sync() 设置为同步

async() 设置为异步

// 构建同步 Get 请求
Forest.get("/");
// 构建异步 Get 请求
Forest.get("/").setAsync(true);
// 构建同步 Get 请求
Forest.get("/").setAsync(false);
// 构建异步 Get 请求
Forest.get("/").async();
// 构建同步 Get 请求
Forest.get("/").sync();
1
2
3
4
5
6
7
8
9
10

# 异步和回调函数

在发送异步请求的情况下,接口调用线程不会被阻塞,所以也不会等待请求的响应结果,那么如何去接受异步返回的数据呢?

第一种方法,就是使用回调函数

Forest.get("/foo")                          // 创建 GET 请求
        .async()                            // 设置为异步
        .onSuccess(((data, req, res) -> {   // 设置 OnSuccess 回调函数 (在请求成功返回时调用)
        // data 为响应成功后返回的反序列化过的数据
        // req 为Forest请求对象,即 ForestRequest 类实例
        // res 为Forest响应对象,即 ForestResponse 类实例
        }))
        .onError(((ex, req, res) -> {       // 设置 OnError 回调函数 (在请求失败时调用)
        // ex 为请求过程可能抛出的异常对象
        // req 为Forest请求对象,即 ForestRequest 类实例
        // res 为Forest响应对象,即 ForestResponse 类实例
        }))
        .execute();                         // 发送请求
1
2
3
4
5
6
7
8
9
10
11
12
13

# Async/Await 风格

自 Ajax 流行开始,回调函数的异步处理方式就已经深入人心,这种方法虽好,但也有不少问题

比如回调地狱:很容易写出在A请求的回调函数中调用B请求,然后在B请求的回调函数中调用C请求,这样的套娃代码

另一个问题,就是执行回调函数所在的线程和调用接口的线程并非同一个线程,这就会引入并发和锁的问题,处理的时候需要谨慎对待

为了解决这些问题,Forest 引入了第二种方法

(从 1.5.27版本后开始支持ForestFuture)

String result = Forest.get("/foo") // 创建 GET 请求
        .async()                   // 设置为异步
        .executeAsFuture()         // 发送请求,并返回 ForestFuture 对象
        .await()                   // 阻塞线程并等待请求响应,成功响应后会返回 ForestResponse 对象
        .get(String.class);        // 调用 ForestResponse 的 get 方法进行转换数据并返回结果
1
2
3
4
5

友情提示

这里的get(String.clss)方法调用的是 ForestResponse 对象的 get(Class<T>) 接口, 是一种后验的数据转换

该接口的具体使用方式请参见《后验类型》

这种方式相比回调函数方式,更为直观,也更类似同步方式

同时发送和接受多个异步请求时,更能体现它的好处

ForestFuture f1 = Forest.get("/foo") // 创建第一个 GET 请求
        .async()                     // 设置为异步
        .addQuery("id", 0)           // 设置 Query 参数
        .executeAsFuture();          // 发送请求并返回 ForestFuture 对象

ForestFuture f2 = Forest.get("/bar") // 创建第二个 GET 请求
        .async()                     // 设置为异步
        .addQuery("id", 1)           // 设置 Query 参数
        .executeAsFuture();          // 发送请求并返回 ForestFuture 对象

// 在这里并不阻塞线程,可以做些其它事情
doSomething();        

// Forest.await 方法会阻塞线程并同时等待多个请求
// 这里同时等待 f1 和 f2 这两个请求
// 只有当这两个请求都完成时,会返回 ForestResponse 对象列表
// 并继续往下执行
Forest.await(f1, f2).forEach(res -> {          // 遍历每个 ForestResponse 对象
        String result = res.get(String.class); // 从 ForestResponse 中取出数据
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

批量发送和等待多个异步请求

// new 一个 ForestFuture 对象列表
List<ForestFuture> futures = new LinkedList<>();
for (int i = 0; i < 100; i++) {     // 循环100次
    futures.add(Forest.get("/data") // 创建请求,并添加到 futures 列表中
        .async()                    // 设置为异步
        .addQuery("id", i)          // 设置 Query 参数
        .executeAsFuture());        // 发送请求,返回 ForestFuture 对象
}

Forest.await(futures).forEach(res -> {     // 等待这100个请求,然后进行遍历
    String result = res.get(String.class); // 从 ForestResponse 中取出数据
});
1
2
3
4
5
6
7
8
9
10
11
12

更简化的方式

// new 一个 ForestFuture 对象列表
List<ForestFuture> futures = new LinkedList<>();
for (int i = 0; i < 100; i++) {     // 循环100次
    futures.add(Forest.get("/data") // 创建请求,并添加到 futures 列表中
        .async()                    // 设置为异步
        .addQuery("id", i)          // 设置 Query 参数
        .executeAsFuture());        // 发送请求,返回 ForestFuture 对象
}

Forest.await(futures, res -> {             // 等待这100个请求,然后进行遍历
    String result = res.get(String.class); // 从 ForestResponse 中取出数据
});
1
2
3
4
5
6
7
8
9
10
11
12

# Kotlin 协程

1.5.27版本开始 Forest 支持 Kotlin 的协程,而默认情况下并不开启,开启方式请参见《开启 Kotlin 协程》

除了这种全局配置外,Forest 也允许通过编程式接口设置某个具体请求的异步模式

Forest.get("/foo")
        .async()
        // 设置为 Kotlin 协程
        .asyncMode(ForestAsyncMode.KOTLIN_COROUTINE);
1
2
3
4

也可以切换回默认的线程池模式

Forest.get("/foo")
        .async()
        // 设置为 Kotlin 协程
        .asyncMode(ForestAsyncMode.PLATFORM);
1
2
3
4
帮助我们改善此文档 (opens new window)
上次更新: 2023/03/07, 12:59:48
⚓ 回调函数
🥯 Cookie

← ⚓ 回调函数 🥯 Cookie→

Theme by Vdoing | Copyright © 2016-2023 公子骏 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式