9. 一个简单的示例
大约 3 分钟
9. 一个简单的示例
截止目前,我们一直专注于构建基于协程 API 的框架支持,这次我们用这些框架来写个简单的示例,并以此来结束整个系列的内容。
准备工作
在本文当中,我将使用前文实现好的 Task
来发起一个简单的网络请求。
我会借助一些已有的框架来完成这次的目标:
cpp-httplib/0.10.4
openssl/3.0.2
nlohmann_json/3.10.5
这些框架可以通过 conan 很轻松的完成安装。
示例实现
首先我们给出发起网络请求的核心代码:
// 用协程包装网络请求,请求的处理调度到 std::async 上
Task<std::string, AsyncExecutor> http_get(std::string host, std::string path) {
httplib::Client cli(host);
// 阻塞地发起网络请求
auto res = cli.Get(path.c_str());
if (res) {
// 返回响应内容,类型为 std::string
co_return res->body;
} else {
co_return httplib::to_string(res.error());
}
}
使用 httplib 来完成网络请求的处理非常简单直接,我们只需要把 url 传入即可。通常我们的网络请求都会在 io 线程当中发起,因此我们将其调度到 AsyncExecutor
上。
接下来,我们再定义一个协程来调用 http_get
:
Task<void, LooperExecutor> test_http() {
try {
debug("send request..."); // Looper 线程上执行
// 发起网络请求,切换线程,当前协程挂起,Looper 线程被释放(此时 Looper 线程可以去调度其他任务)
auto result = co_await http_get("https://api.github.com", "/users/bennyhuo");
// 请求返回,当前协程接着在 Looper 线程上调度执行
debug("done.");
// 业务逻辑处理,解析 json
auto json = nlohmann::json::parse(result);
// 打印 json 内容
debug(json.dump(2));
// 假装这是其他业务处理
debug(json["login"], json["url"]);
} catch (std::exception &e) {
debug(e.what());
}
}
程序运行结果如下:
22:10:54.046 [Thread-08056] (main.cpp:27) test_http: send request...
22:10:54.953 [Thread-08056] (main.cpp:29) test_http: done.
22:10:54.953 [Thread-08056] (main.cpp:31) test_http: {
"avatar_url": "https://avatars.githubusercontent.com/u/6336960?v=4",
"bio": "Google Developer Expert @Kotlin",
"blog": "https://www.bennyhuo.com",
... 中间内容很多,省略掉 ...
"updated_at": "2022-03-23T13:51:26Z",
"url": "https://api.github.com/users/bennyhuo"
}
22:10:54.953 [Thread-08056] (main.cpp:32) test_http: "bennyhuo"
22:10:54.954 [Thread-08056] (main.cpp:33) test_http: "https://api.github.com/users/bennyhuo"
22:10:54.954 [Thread-08056] (main.cpp:34) test_http: "Google Developer Expert @Kotlin"
在这个示例当中,我们没有使用协程来解决阻塞的问题,而是将一个异步的请求封装成同步的代码。test_http
当中的代码全程在 Looper 线程当中执行,尽管中间穿插了一个异步网络请求,但这看上去丝毫没有影响程序的连贯性和简洁性。
小结
本文的内容相对轻松,因为我们终于停止了基于协程的基础 API 的探索。
实际上,如果你发现你用到的某些 API 提供了异步回调,你完全可以使用 Awaiter
对其提供 co_await
的支持。
关于作者
霍丙乾 bennyhuo,Google 开发者专家(Kotlin 方向);《深入理解 Kotlin 协程》 作者(机械工业出版社,2020.6);《深入实践 Kotlin 元编程》 作者(机械工业出版社,2023.8);移动客户端工程师,先后就职于腾讯地图、猿辅导、腾讯视频。
- GitHub:https://github.com/bennyhuo
- 博客:https://www.bennyhuo.com
- bilibili:霍丙乾 bennyhuo
- 微信公众号:霍丙乾 bennyhuo