阻塞与 WASM
前面四部分讲的都是 async_impl::Client。reqwest 还导出另外两套同名的 Client / RequestBuilder / Response:reqwest::blocking 给不想碰 async 的调用方,wasm32-unknown-unknown 目标上的 reqwest::Client 给浏览器。两者和异步客户端的关系完全不同。阻塞客户端是一层包装:每个 Client 一个后台线程,线程里的异步客户端照常走请求主线和连接主线,调用线程只负责送请求、停车等结果。WASM 是另一套实现:没有 tower、没有连接池,一次请求就是一次 fetch(),连接主线整个交给浏览器。
代码分布(按 tag v0.13.5 统计 .rs 行数,含文档注释和测试):src/blocking/ 4217 行,其中 client.rs 1583 行大半是转发给异步 builder 的方法;src/wasm/ 2186 行。
- 阻塞客户端:
ClientHandle起一个current_thread运行时线程,请求经无界mpsc送去、oneshot送回,调用线程在wait::timeout里park;默认 30 秒超时是每段等待的上限,不是总超时;在异步上下文里调用,debug 构建 panic「Cannot drop a runtime ...」,release 构建不检查,current_thread下会死锁到超时;一个Client多一个线程、约 20 µs 的build,单请求延迟和异步客户端同一量级。 - WASM:
if_wasm!/if_hyper!按目标切换实现;请求翻译成RequestInit交给fetch,AbortGuard管取消和超时;ClientBuilder只剩 4 个方法,redirect、Proxy、tls等模块不存在,另有 12 个fetch_*方法只在 WASM 上有;wasm32-unknown-unknown离线cargo check能过,依赖从 103 个降到 63 个。
flowchart TB user["调用方代码"] --> blk["blocking Client"] user --> asy["async Client"] user --> wsm["wasm Client"] blk -- "mpsc 和 oneshot" --> rt["后台运行时线程"] rt --> asy asy --> stack["tower 栈与 hyper-util"] wsm --> fetch["浏览器 fetch"]
💬 关联讨论
发起讨论加载中...