新闻详情

新闻详情

首页 / 资讯中心 / 详情

PHP使用Guzzle发起的异步请求示例详解

发布时间:2026/9/27 23:06:19来源:尧图网络
PHP使用Guzzle发起的异步请求示例详解
Guzzle中的异步请求使用Guzzle发起异步请求Guzzle是一个PHP的HTTP客户端它在发起http请求时不仅可以同步发起还可以异步发起。12345678$clientnewClient();$requestnewRequest(GET,http://www.baidu.com);$promise$client-sendAsync($request)-then(function($response) {echo$response-getBody();});// todo somethingecho1;$promise-wait();PHP发起HTTP请求的几种方式curl使用libcurl库允许你与各种的服务器使用各种类型的协议进行连接和通讯。stream通过流的方式获取和发送远程文件该功能需要ini配置allow_url_fopenon。关于php的流更多参考PHP流Stream的概述与使用详解在guzzle中可以兼容使用这两种的任意一种或者是用户自定义的http handler1234567891011121314151617181920functionchoose_handler(){$handler null;if(function_exists(curl_multi_exec) function_exists(curl_exec)) {$handler Proxy::wrapSync(newCurlMultiHandler(),newCurlHandler());}elseif(function_exists(curl_exec)) {$handlernewCurlHandler();}elseif(function_exists(curl_multi_exec)) {$handlernewCurlMultiHandler();}if(ini_get(allow_url_fopen)) {$handler$handler? Proxy::wrapStreaming($handler,newStreamHandler()):newStreamHandler();}elseif(!$handler) {thrownew\RuntimeException(GuzzleHttp requires cURL, the .allow_url_fopen ini setting, or a custom HTTP handler.);}return$handler;}可以看出guzzle会优先使用curl然后选择使用streamProxy::wrapStreaming($handler, new StreamHandler())是一个流包装器。12345678910publicstaticfunction wrapStreaming(callable $default,callable $streaming) {returnfunction (RequestInterface $request, array $options) use ($default, $streaming) {returnempty($options[stream])? $default($request, $options): $streaming($request, $options);};}什么是URIURI的组成URIUniform Resource Identifier统一资源标识符。scheme:[//[user:password]host[:port]][/]path[?query][#fragment]请求的组装Guzzle发起请求大致分为两个阶段第一阶段负责将需要请求的uri组装成各种内部定义的类。Client类这是一个发起客户端的调用者后续所有的调用需要基于这个负责的类实现它负责提供一个 handler ,这是一个客户端发起http请求的句柄其中Guzzle实现curl和stream调用的无感知就是在这里实现的同时开发者也可以自定义请求协议。123456789101112131415161718192021// 根据系统当前状态选择一个发起Http请求的协议的方法句柄functionchoose_handler(){$handler null;if(function_exists(curl_multi_exec) function_exists(curl_exec)) {$handler Proxy::wrapSync(newCurlMultiHandler(),newCurlHandler());}elseif(function_exists(curl_exec)) {$handlernewCurlHandler();}elseif(function_exists(curl_multi_exec)) {$handlernewCurlMultiHandler();}if(ini_get(allow_url_fopen)) {$handler$handler? Proxy::wrapStreaming($handler,newStreamHandler()):newStreamHandler();}elseif(!$handler) {thrownew\RuntimeException(GuzzleHttp requires cURL, the .allow_url_fopen ini setting, or a custom HTTP handler.);}return$handler;}Request类负责定义一个uriPromise类这个类负责承载类请求发起前的各种准备工作完成后的结果还包括两个回调请求成功回调、请求失败回调,同时请求发起中的队列延迟等处理也是在这个类里。其中组装阶段最重要的方法是私有方法private function transfer(RequestInterface $request, array $options)它负责将用户通过各种方法传入的uri和client类的各种属性组合然后使用这些属性生成一个新的类 Promise 类。请求的发起Client的各种属性组装完成后就可以使用得到的Promise类发起http请求了这里主要是通过一个 wait() 方法。同步调用与异步调用在同步方法内部的调用同步方法是在内部组装好一个Promise之后立刻发起wait()调用。12345publicfunction send(RequestInterface $request, array $options []){$options[RequestOptions::SYNCHRONOUS] true;return$this-gt;sendAsync($request, $options)-gt;wait();}wait的实现wait() 方法的实现逻辑也很简单递归调用wait()方法直到result属性不是PromiseInterface实现类或者state不是pending然后将结果逐层输出。这里说一下这个state的pending状态这是一个PromiseInterface实现类的初始化状态表示改实现类还没有完成需要继续wait。1234567891011121314151617publicfunction wait($unwrap true){$this-gt;waitIfPending();$inner $this-gt;result instanceof PromiseInterface? $this-gt;result-gt;wait($unwrap): $this-gt;result;if($unwrap) {if($this-gt;result instanceof PromiseInterface|| $this-gt;state self::FULFILLED) {return$inner;}else{// Its rejected so unwrap and throw an exception.throwexception_for($inner);}}}waitIfPending() 如果promise类还处于pending状态就执行。主要是执行改实现类的waitFn方法。最外层promise执行完成后执行queue()-run() 这个方法内部循环执行队列内方法直到队列为空。至此Guzzle就能将组装进来的多个request和各种方法执行完毕。123456789101112131415161718192021222324252627privatefunctionwaitIfPending(){if($this-state ! self::PENDING) {return;}elseif($this-waitFn) {$this-invokeWaitFn();}elseif($this-waitList) {$this-invokeWaitList();}else{// If theres not wait function, then reject the promise.$this-reject(Cannot wait on a promise that has .no internal wait function. You must provide a wait .function when constructing the promise to be able to .wait on a promise.);}queue()-run();if($this-state self::PENDING) {$this-reject(Invoking the wait callback did not resolve the promise);}}publicfunctionrun(){/** var callable $task */while($taskarray_shift($this-queue)) {$task();}}waitFn是什么回到前面提到的transfer()函数。123$handler$options[handler];// 返回一个promise类这个类有一个属性是waitFnreturnPromise\promise_for($handler($request,$options));这里我们看 $handler 是什么它是一个HandleStack类就是我们在new Client时选择的发起Http请求的协议的方法句柄实例化的类。br /之后的调用依次是 HandleStack-__invoke、RedirectMiddleware-__invoke、PrepareBodyMiddleware-__invoke。执行$fn($request, $options);方法经过前面的逐层处理此时的$fn就是HandleStack内部的Proxy包装的方法无论使用哪种协议都会在各自的实现里实例化一个拥有waitFn的Promise的实例。1234567// curl的实现$promisenewPromise([$this,execute],function()use($id) {return$this-cancel($id);});复制讲解由此可以直到waitFn方法就是各自协议的实现类的请求发起方法。then() 方法会将promise本身再封装一层promise并将原先的waitFn和then()的回调方法打包进waitFnList属性里。queue() 是的入队时机当请求执行完成后依次调用 processMessages()、promise-resolve()、settle()、FulfilledPromise-then()将请求结果插入队列。1234567891011$queue-add(staticfunction()use($p,$value,$onFulfilled) {if($p-getState() self::PENDING) {try{$p-resolve($onFulfilled($value));}catch(\Throwable$e) {$p-reject($e);}catch(\Exception$e) {$p-reject($e);}}});以上就是PHP使用Guzzle发起的异步请求示例详解的详细内容
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

苹果序列号查询全解析:从底层逻辑到二手交易避坑实战 2026/9/27 23:49:49

苹果序列号查询全解析:从底层逻辑到二手交易避坑实战

1. 苹果序列号查询的底层逻辑与核心价值很多人第一次接触“序列号查询”这个概念,是因为买了一台二手 iPhone 或者 Mac,想确认卖家说的“全新未激活”“国行正品”到底靠不靠谱。苹果的序列号就像设备的身份证号,它不只是一串随机字符&#x…

阅读更多 →
Laravel Lang 中库尔德语(ckb)翻译完成度报告:15 个缺失键位全解析与补全指南 2026/9/27 23:49:49

Laravel Lang 中库尔德语(ckb)翻译完成度报告:15 个缺失键位全解析与补全指南

后端 【免费下载链接】lang List of 128 languages for Laravel Framework, Laravel Jetstream, Laravel Fortify, Laravel Breeze, Laravel Cashier, Laravel Nova and Laravel UI. 项目地址: https://gitcode.com/gh_mirrors/la/lang 点击查看 免费下载 本指南以…

阅读更多 →
3个坑让你省5万:内蒙古高等级公路建设开发有限责任公司网站对比评测 2026/9/27 23:49:49

3个坑让你省5万:内蒙古高等级公路建设开发有限责任公司网站对比评测

3个坑让你省5万:内蒙古高等级公路建设开发有限责任公司网站对比评测 找建站公司最怕什么?不是功能做不全,而是报价单上那些看不懂的术语,最后结账时才发现多花了几万块冤枉钱。很多老板拿着需求去问价,销售嘴里蹦出“微服务架构”、“全栈云原生”,转…

阅读更多 →
UG数控编程从入门到精通:工艺思维与实战避坑指南 2026/9/27 23:49:49

UG数控编程从入门到精通:工艺思维与实战避坑指南

1. 为什么UG数控编程值得你花时间啃下来干了十几年机加工,从手编宏程序到现在的CAM软件,我最大的感受就是:UG(现在官方叫Siemens NX)在数控编程这块,依然是国内模具、汽车、航空零件加工厂里最硬的那块敲门…

阅读更多 →
基于YOLOv8的多端车流检测系统源码拆解与实战调优 2026/9/27 23:49:43

基于YOLOv8的多端车流检测系统源码拆解与实战调优

简介:本资源是一套基于YOLOv8构建的多端车流检测系统完整源码包,面向计算机视觉学习者、交通监控方向开发者及需要目标检测实战项目的学生与工程师,帮助其快速搭建可运行的车辆流量检测应用。压缩包共396个文件,约16.93MB&#xf…

阅读更多 →
Java数字签名与证书生成实战:从keytool到Bouncy Castle全解析 2026/9/27 23:49:43

Java数字签名与证书生成实战:从keytool到Bouncy Castle全解析

简介:围绕Java数字签名与数字证书的源码示例,面向中高级Java开发者及安全编程初学者,演示如何在网络通信中利用非对称加密保障数据完整性与发送方身份验证。压缩包为RAR格式,体积仅17KB,便于快速下载与阅读&#xff1b…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉