PHP协程的thunkify自动执行器的详细介绍(代码)

PHP协程的thunkify自动执行器的详细介绍(代码)

内容导读

收集整理的这篇技术教程文章主要介绍了PHP协程的thunkify自动执行器的详细介绍(代码),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5259字,纯文字阅读大概需要8分钟

内容图文

本篇文章给大家带来的内容是关于PHP协程的thunkify自动执行器的详细介绍(代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

高阶函数

在我们实现自动调度(器)函数前,我们先来理解下高阶函数

thunk函数

# 先求值再传参function func(m){
return m * 2;

 }f(x + 5);// 等同于# 先传参再求值var thunk = function () {
return x + 5;};function func(thunk){
return thunk() * 2;}# 这段我们在python或一些语言里,概念叫高阶函数# 因为php是解释性动态语言,所以函数可以当参数传入# 这里python,js,php下函数都是可以传参的

PHP版本的thunkify函数

thunkify实现原理:

1、包装一次原始函数名,然后返回一个第一次匿名函数(并携带包装函数): return function () use ($func){$args = func_get_args();}

2、然后再获取该匿名函数的参数,并在上一次第一次匿名函数体内返回一次带回调参数的第二次匿名函数(并携带上一次环境上下文): return function ($callback) use ($args, $func){}

3、调用包装函数,参数为:第一次匿名函数调用的参数+一个回调函数

function thunkify($func){

return function () use ($func) {



$args = func_get_args();



return function ($callback) use ($args, $func) {





array_push($args, $callback);





return $func(...$args);



};
};};$printStr = function($p1, $p2, $callback) {

$callback($p1, $p2);};$printStrThunkify = thunkify($printStr);$printStrThunkify(...["foo", "bar"])(function (...$p) {

var_dump($p);});# outputarray(2) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"}

只能执行一次回调的thunkify函数

function thunkify($func){

return function () use ($func) {



$args = func_get_args();



return function ($callback) use ($args, $func) {





// 原本的获取参数,回调会多次执行





// array_push($args, $callback);





 // 增加回调只能执行一次





$callbackCalled = false;





array_push($args, function (...$params) use ($callback, &$callbackCalled) {







if ($callbackCalled) return ;







$callbackCalled = true;







$callback(...$params);





});





return $func(...$args);



};

};};$printStr = function($p1, $p2, $callback) {

$callback($p1, $p2);

$callback($p1, $p2); //我们增加一次回调};$printStrThunkify = thunkify($printStr);$printStrThunkify(...["foo", "bar"])(function (...$p) {

var_dump($p);});# outputarray(2) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"}

看到这里,你可能还在疑惑,thunkify函数其实只是帮我们包装了一次有回调函数的高阶函数而已
不过这里到底有什么用处呢,在普通场景下确实用户不大(可能用处单纯就在做一些前后置函数包装也是用处的,类似python的装饰)
但是,但是,但是在生成器协程里,Thunkify函数可以用于生成器协程的自动流程管理。

生成器协程的自动执行基础理解

每一次yield出来的结果都是一个thunk函数的回调

function thunkify($func){

return function () use ($func) {



$args = func_get_args();



return function ($callback) use ($args, $func) {





$callbackCalled = false;





array_push($args, function (...$params) use ($callback, &$callbackCalled) {







if ($callbackCalled) return ;







$callbackCalled = true;







$callback(...$params);





});





return $func(...$args);



};

};};$printStr1 = function($p1, $callback) {

$callback($p1);};$printStr2 = function($p1, $callback) {

$callback($p1);};$printStrThunkify1 = thunkify($printStr1);$printStrThunkify2 = thunkify($printStr2);function gen(){

global $printStrThunkify1, $printStrThunkify2;

$r1 = yield $printStrThunkify1("1");

var_dump($r1);

$r2 = yield $printStrThunkify2("2");

var_dump($r2);}$gen = gen();// 手动回调, 模拟自动执行基础理解$value = $gen->current();$value(function ($p1) use($gen) {

$value = $gen->send($p1);

$value(function ($p1) use($gen) {



$value = $gen->send($p1);



var_dump($value);

});});

自动执行器

我们这里只是实现上面的手动回调执行
增加了一个自动执行器,把生成器协程传入后讲自动执行生成器协程

function thunkify($func){

return function () use ($func) {



$args = func_get_args();



return function ($callback) use ($args, $func) {





$callbackCalled = false;





array_push($args, function (...$params) use ($callback, &$callbackCalled) {







if ($callbackCalled) return ;







$callbackCalled = true;







$callback(...$params);





});





return $func(...$args);



};

};};$printStr1 = function($p1, $callback) {

sleep(2);

$callback($p1);};$printStr2 = function($p1, $callback) {

sleep(5);

$callback($p1);};$printStrThunkify1 = thunkify($printStr1);$printStrThunkify2 = thunkify($printStr2);function gen(){

global $printStrThunkify1, $printStrThunkify2;

$r1 = yield $printStrThunkify1("1");

var_dump($r1);

$r2 = yield $printStrThunkify2("2");

var_dump($r2);}function autoCaller(Generator $gen){

// 注意这里的$next use 引入作用域必须带上&, 否则无法识别

$next = function ($p1) use ($gen, &$next) {



if (is_null($p1)) { //此处获取第一次yeild的回调





$result = $gen->current();



} else {





// send后返回的是下一次的yield值





$result = $gen->send($p1);



}



// 是否生成器迭代完成



// 迭代器生成完成,不再迭代执行(自动执行器返回停止)



if (!$gen->valid()) {





return ;



}



$result($next);

};

$next(null);}$gen1 = gen();//$gen2 = gen();autoCaller($gen1);//autoCaller($gen2);# outputstring(1) "1"string(1) "2"# 如果我们打开上面的两个sleep()注释# output# 等待2秒string(1) "1"# 等待5秒string(1) "2"# 因为这里我们的thunk里执行的实际函数是同步的代码,所以整体是阻塞的后续代码执行的

总结

只要执行 autoCaller 函数,生成器就会自动迭代完成。这样一来,异步操作不仅可以写得像同步操作,而且一行代码就可以执行。

Thunkify函数并不是 生成器协程 函数自动执行的唯一方案。

因为自动执行的关键是,必须有一种机制,自动控制 生成器协程 函数的流程,接收和交还程序的执行权。

回调函数可以做到这一点,Promise 对象也可以做到这一点。

以上就是PHP协程的thunkify自动执行器的详细介绍(代码)的详细内容,更多请关注Gxl网其它相关文章!

内容总结

以上是为您收集整理的PHP协程的thunkify自动执行器的详细介绍(代码)全部内容,希望文章能够帮你解决PHP协程的thunkify自动执行器的详细介绍(代码)所遇到的程序开发问题。 如果觉得技术教程内容还不错,欢迎将网站推荐给程序员好友。

内容备注

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。


本文关键词:

联系我们

在线咨询:点击这里给我发消息

邮件:w420220301@qq.com