>  기사  >  백엔드 개발  >  PHP 코루틴(코드)의 thunkify 자동 실행기 상세 소개

PHP 코루틴(코드)의 thunkify 자동 실행기 상세 소개

不言
不言앞으로
2018-10-09 14:08:272638검색

이 글은 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);
});

# output
array(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);
});

# output
array(2) {
  [0]=>
  string(3) "foo"
  [1]=>
  string(3) "bar"
}

이것을 보면 여전히 혼란스러울 수 있지만 thunkify 함수는 실제로 우리에게 도움이 됩니다. 단지 콜백 함수로 고차 함수를 래핑할 뿐입니다
하지만 여기서 무슨 소용이 있을까요? 일반적인 시나리오에서는 사용자가 많지 않습니다(파이썬 장식과 유사하게 일부 사전 및 사후 함수를 간단히 래핑하는 데 사용될 수 있습니다).
하지만, 단, 제너레이터 코루틴에서는 Thunkify 함수를 사용하여 제너레이터 코루틴의 자동 프로세스 관리를 수행할 수 있습니다. 生成器协程里,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);

# output
string(1) "1"
string(1) "2"

# 如果我们打开上面的两个sleep()注释
# output

# 等待2秒
string(1) "1"
# 等待5秒
string(1) "2"

# 因为这里我们的thunk里执行的实际函数是同步的代码,所以整体是阻塞的后续代码执行的

总结

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

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

因为自动执行的关键是,必须有一种机制,自动控制 生成器协程

제너레이터 코루틴 자동 실행에 대한 기본 이해

각 Yield의 결과는 썽크 함수의 콜백입니다🎜rrreee🎜자동 실행기🎜🎜위의 수동 콜백 실행만 구현합니다🎜제너레이터를 전달한 후 자동 실행기를 추가했습니다. 코루틴에서는 생성기 코루틴🎜rrreee🎜요약🎜🎜 autoCaller 함수가 실행되는 한 생성기는 자동으로 반복하여 완료됩니다. 이러한 방식으로 비동기 작업은 동기 작업처럼 작성될 수 있을 뿐만 아니라 한 줄의 코드로 실행될 수도 있습니다. 🎜🎜Thunkify 기능은 제너레이터 코루틴 기능의 자동 실행을 위한 유일한 솔루션은 아닙니다. 🎜🎜자동 실행의 핵심은 제너레이터 코루틴 함수의 흐름을 자동으로 제어하고 프로그램의 실행 권한을 받고 반환하는 메커니즘이 있어야 하기 때문입니다. 🎜🎜콜백 함수가 이를 수행할 수 있으며 Promise 객체도 마찬가지입니다. 🎜

위 내용은 PHP 코루틴(코드)의 thunkify 자동 실행기 상세 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제