在做项目中,经常遇到比如说要发送邮件或者短信验证码,或者导出任务等比较耗时的任务,采用同步方式就可能用户需要等待了,体验不友好,为了缩短用户等待时间,这时可以采用异步的方式,比如消息队列等,我想到一个小方法,去触一个脚本去执行,php的exec函数能执行linux命令,可以用来执行脚本,但是经过测试,发现程序还是要等待脚本执行完毕才返回。于是就想到了popen
定义和用法
popen() 函数打开进程文件指针。
语法
popen(command,mode)
参数 描述
command 必需。规定要执行的命令。
mode 必需。规定连接模式。 可能的值:
r: 只读。
w: 只写 (打开并清空已有文件或创建一个新文件)
说明
打开一个指向进程的管道,该进程由派生指定的 command 命令执行而产生。
返回一个和 fopen() 所返回的相同的文件指针,只不过它是单向的(只能用于读或写)并且必须用 pclose() 来关闭。此指针可以用于 fgets(),fgetss() 和 fwrite()。
若出错,则返回 false。
可以使用popen去执行一些命令,还不会等待
接下来做个小实验:
目录结构:
BaAGeedeMacBook-Pro:async_test dangliuhui$ tree . ├── AsyncTask.php ├── script │ └── test_1.php ├── task_map_config.php └── test.phpAsyncTask.php为任务主要类:
class AsyncTask { protected static $map = []; public static function run($script_name, $data = []) { self::$map = include_once './task_map_config.php'; $script_path = self::getTask($script_name); $where = ''; foreach ($data as $k => $v) { $where .= ' --' . $k . '=' . $v; } $command = PHP_BINARY . ' ' . $script_path . $where . ' &'; $handle = popen($command, 'w'); pclose($handle); return $where; } public static function getTask($script_name) { return self::$map[$script_name]; } }task_map_config.php主要配置了任务名称和其对应的脚本路径:
return [ // 'task_name'=>'script_path' 'test_1' => __DIR__ . '/script/test_1.php' ];接下来编写脚本文件(script/test_1.php):
echo '脚本开始运行' . PHP_EOL; $s_t = microtime(true); $fields = [ 'name:', 'age:', 'aaa:', 'bbb:', 'ccc:', ]; //php cli模式下接收脚本参数 $where = getopt('', $fields); var_dump('接收到的参数:' . json_encode($where, JSON_UNESCAPED_UNICODE)); foreach ($where as $k => $v) { echo sprintf('%s=>%s', $k, $v) . PHP_EOL; sleep(1); } $e_t = microtime(true); echo '脚本执行结束,运行时间:' . ($e_t - $s_t);
其实很简单,模拟耗时操作,打印接收变量值
解析来就是怎么去调用这个脚本,异步执行了。
test.php为测试文件:
include './AsyncTask.php'; //test $data = [ 'name' => 'hahha哈哈哈', 'age' => 123, 'aaa' => 'jkhgf9876', 'bbb' => 'bbbbb', 'ccc' => 'ccccccc', ]; echo 'start' . PHP_EOL; echo AsyncTask::run('test_1', $data) . PHP_EOL; echo 'end' . PHP_EOL . PHP_EOL;
直接AsyncTask::run('任务名','脚本所需参数数组');就可以啦
查看输出结果:
start --name=hahha哈哈哈 --age=123 --aaa=jkhgf9876 --bbb=bbbbb --ccc=ccccccc end 脚本开始运行 string(106) "接收到的参数:{"name":"hahha哈哈哈","age":"123","aaa":"jkhgf9876","bbb":"bbbbb","ccc":"ccccccc"}" name=>hahha哈哈哈 age=>123 aaa=>jkhgf9876 bbb=>bbbbb ccc=>ccccccc 脚本执行结束,运行时间:5.0003838539124 Process finished with exit code 0
可以很明显的看出虽然test.php早早的已经执行完毕,但是耗时的tet_1脚本还在继续执行,这样就实现了异步处理。
里面的细节比如popen详情,php cli模式下获取参数等你可以google一下具体资料。
友情提示:垃圾评论一律封号...