详解PHP实现异步调用的4种方法


Posted in PHP onMarch 14, 2016

浏览器和服务器之间是通过 HTTP 协议进行连接通讯的。这是一种基于请求和响应模型的协议。浏览器通过 URL 向服务器发起请求,Web 服务器接收到请求,执行一段程序,然后做出响应,发送相应的html代码给客户端。

这就有了一个问题,Web 服务器执行一段程序,可能几毫秒就完成,也可能几分钟都完不成。如果程序执行缓慢,用户可能没有耐心等下去,就关闭浏览器了。

而有的时候,我们更本不关心这些耗时的脚本的返回结果,但却还要等他执行完返回,才能继续下一步。
那么有没有什么办法,只是简单的触发调用这些耗时的脚本然后就继续下一步,让这些耗时的脚本在服务端慢慢执行?

经过试验,总结出来几种方法,和大家share:

1. 最简单的办法,就是在返回给客户端的HTML代码中,嵌入AJAX调用,或者,嵌入一个img标签,src指向要执行的耗时脚本。
这种方法最简单,也最快。服务器端不用做任何的调用。
但是缺点是,一般来说Ajax都应该在onLoad以后触发,也就是说,用户点开页面后,就关闭,那就不会触发我们的后台脚本了。
而使用img标签的话,这种方式不能称为严格意义上的异步执行。用户浏览器会长时间等待php脚本的执行完成,也就是用户浏览器的状态栏一直显示还在load。
当然,还可以使用其他的类似原理的方法,比如script标签等等。

2. popen()

resource popen ( string command, string mode );
//打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。

所以可以通过调用它,但忽略它的输出。

pclose(popen("/home/xinchen/backend.php &", 'r'));
这个方法避免了第一个方法的缺点,并且也很快。但是问题是,这种方法不能通过HTTP协议请求另外的一个WebService,只能执行本地的脚本文件。并且只能单向打开,无法穿大量参数给被调用脚本。
并且如果,访问量很高的时候,会产生大量的进程。如果使用到了外部资源,还要自己考虑竞争。

3. 使用CURL
这个方法,设置CUROPT_TIMEOUT为1(最小为1,郁闷)。也就是说,客户端至少必须等待1秒钟。 

$ch = curl_init();
   
  $curl_opt = array(CURLOPT_URL, 'http://www.example.com/backend.php',
                CURLOPT_RETURNTRANSFER, 1,
                CURLOPT_TIMEOUT, 1,);
   
  curl_setopt_array($ch, $curl_opt);
   
  curl_exec($ch);
   
  curl_close($ch);

4. 使用fsockopen
这个方法应该是最完美的,但是缺点是,你需要自己拼出HTTP的header部分。

$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
  if (!$fp) {
    echo "$errstr ($errno)<br />\n";
  } else {
    $out = "GET /backend.php / HTTP/1.1\r\n";
    $out .= "Host: www.example.com\r\n";
    $out .= "Connection: Close\r\n\r\n";
   
    fwrite($fp, $out);
    /*忽略执行结果
  while (!feof($fp)) {
  echo fgets($fp, 128);
  }*/
    fclose($fp);
  }

所以,总体来看,最好用,最简单的还是第一种方法。
最完美的应该是最后一种,但是比较复杂。
以上就是4种php实现异步调用的方法,希望对大家的学习有所帮助。

PHP 相关文章推荐
php调用mysql存储过程
Feb 14 PHP
在命令行下运行PHP脚本[带参数]的方法
Jan 22 PHP
收集的二十一个实用便利的PHP函数代码
Apr 22 PHP
PHP笔记之:基于面向对象设计的详解
May 14 PHP
解析PHP中一些可能会被忽略的问题
Jun 21 PHP
PHP生成数组再传给js的方法
Aug 07 PHP
php通过exif_read_data函数获取图片的exif信息
May 21 PHP
PHP读书笔记整理_结构语句详解
Jul 01 PHP
PHP中FTP相关函数小结
Jul 15 PHP
php类的自动加载操作实例详解
Sep 28 PHP
利用php获得flv视频长度的实例代码
Oct 26 PHP
PHP设计模式之迭代器模式Iterator实例分析【对象行为型】
Apr 26 PHP
ThinkPHP框架安全实现分析
Mar 14 #PHP
php语言的7种基本的排序方法
Dec 28 #PHP
php实现图片上传并利用ImageMagick生成缩略图
Mar 14 #PHP
YII Framework框架教程之国际化实现方法
Mar 14 #PHP
YII Framework框架教程之缓存用法详解
Mar 14 #PHP
YII Framework框架教程之安全方案详解
Mar 14 #PHP
YII Framework框架教程之日志用法详解
Mar 14 #PHP
You might like
资料注册后发信小技巧
2006/10/09 PHP
CI框架表单验证实例详解
2016/11/21 PHP
ThinkPHP实现简单登陆功能
2017/04/28 PHP
PHP多进程之pcntl_fork的实例详解
2017/10/15 PHP
基于PHP实现生成随机水印图片
2020/12/09 PHP
JavaScript游戏之优化篇
2010/11/08 Javascript
Js如何判断客户端是PC还是手持设备简单分析
2012/11/22 Javascript
js+css 实现遮罩居中弹出层(随浏览器窗口滚动条滚动)
2013/12/11 Javascript
Javascript中this的用法详解
2014/09/22 Javascript
jQuery实现的图文高亮滚动切换特效实例
2015/08/10 Javascript
仅9张思维导图帮你轻松学习Javascript 就这么简单
2016/06/01 Javascript
javascript 正则表达式分组、断言详解
2017/04/20 Javascript
解决JS内存泄露之js对象和dom对象互相引用问题
2017/06/25 Javascript
NodeJS加密解密及node-rsa加密解密用法详解
2018/10/12 NodeJs
详解基于iview-ui的导航栏路径(面包屑)配置
2019/02/22 Javascript
详解vue-router的Import异步加载模块问题的解决方案
2020/05/13 Javascript
Vue实现简单的跑马灯
2020/05/25 Javascript
使用Element的InfiniteScroll 无限滚动组件报错的解决
2020/07/27 Javascript
[01:31](回顾)杀出重围,决战TI之巅
2014/07/01 DOTA
[02:42]岂曰无衣,与子同袍!DOTA2致敬每一位守护人
2020/02/17 DOTA
简单讲解Python中的闭包
2015/08/11 Python
python函数中return后的语句一定不会执行吗?
2017/07/06 Python
Python实现矩阵相乘的三种方法小结
2018/07/26 Python
python模拟登陆,用session维持回话的实例
2018/12/27 Python
对pyqt5多线程正确的开启姿势详解
2019/06/14 Python
Python参数传递机制传值和传引用原理详解
2020/05/22 Python
python实现模拟器爬取抖音评论数据的示例代码
2021/01/06 Python
在HTML5中如何使用CSS建立不可选的文字
2014/10/17 HTML / CSS
HTML5之SVG 2D入门6—视窗坐标系与用户坐标系及变换概述
2013/01/30 HTML / CSS
Kipling凯浦林美国官网:世界著名时尚休闲包袋品牌
2016/08/24 全球购物
SmartBuyGlasses中国:唯视良品(销售名牌太阳镜、墨镜和眼镜框)
2017/07/03 全球购物
俄罗斯香水在线商店:AromaCode
2019/12/04 全球购物
火锅店的活动方案
2014/08/15 职场文书
幼儿教师暑期培训方案
2014/08/27 职场文书
vue如何在data中引入图片的正确路径
2022/06/05 Vue.js
MySQL下载安装配置详细教程 附下载资源
2022/09/23 MySQL