Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Einführung in den automatischen Executor der PHP-Coroutine Thunkify (Code)

Detaillierte Einführung in den automatischen Executor der PHP-Coroutine Thunkify (Code)

不言
不言nach vorne
2018-10-09 14:08:272638Durchsuche

Dieser Artikel bietet Ihnen eine detaillierte Einführung (Code) zum automatischen Executor von PHP. Er hat einen gewissen Referenzwert. Ich hoffe, er wird Ihnen hilfreich sein.

Funktion höherer Ordnung

Bevor wir die automatische Planungsfunktion implementieren, wollen wir zunächst die Funktion höherer Ordnung verstehen

Thunk-Funktion

# 先求值再传参
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-Version der Thunkify-Funktion

Thunkify-Implementierungsprinzip:

1. Wickeln Sie den ursprünglichen Funktionsnamen einmal ein und geben Sie dann eine erste anonyme Funktion zurück (und tragen Sie die Wrapping-Funktion): return function () verwenden ($func){$args = func_get_args();}

2. Rufen Sie dann die Parameter der anonymen Funktion ab und geben Sie das zweite Mal mit Rückrufparametern im Hauptteil der letzten ersten anonymen Funktion zurück ( und trägt den letzten Umgebungskontext): Rückgabefunktion ($callback) use ($args, $func){}

3. Rufen Sie die Wrapper-Funktion auf, die Parameter sind: die Parameter des ersten anonymen Funktionsaufrufs + Eine Rückruffunktion

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"
}

Eine Thunkify-Funktion, die einen Rückruf nur einmal ausführen kann

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"
}

Wenn Sie das sehen, fragen Sie sich vielleicht immer noch, dass die Thunkify-Funktion uns eigentlich nur dabei hilft, eine Funktion auf hoher Ebene einzuschließen Eine Callback-Funktion. Es handelt sich lediglich um eine Funktion erster Ordnung.
Aber was nützt es hier wirklich? Dekoration)
Aber, aber, Aber in 生成器协程 kann Thunkify函数 zur automatischen Prozessverwaltung von 生成器协程 verwendet werden.

Grundlegendes Verständnis der automatischen Ausführung von Generator-Coroutinen

Das Ergebnis jeder Ausbeute ist ein Rückruf einer Thunk-Funktion

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);
    });
});

Automatischer Executor

Hier sind wir nur Implementieren Sie die obige manuelle Rückrufausführung
und fügen Sie einen automatischen Executor hinzu. Nach der Übergabe der Generator-Coroutine führen wir die Generator-Coroutine automatisch aus

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里执行的实际函数是同步的代码,所以整体是阻塞的后续代码执行的

Zusammenfassung

Führen Sie einfach die Funktion autoCaller aus. Der Generator iteriert automatisch bis zum Abschluss. Auf diese Weise können asynchrone Operationen nicht nur wie synchrone Operationen geschrieben, sondern auch in einer Codezeile ausgeführt werden. Die

Thunkify-Funktion ist nicht die einzige Lösung für die automatische Ausführung der 生成器协程-Funktion.

Denn der Schlüssel zur automatischen Ausführung liegt darin, dass es einen Mechanismus geben muss, um den Ablauf der 生成器协程-Funktion automatisch zu steuern und die Ausführungsrechte des Programms zu empfangen und zurückzugeben.

Callback-Funktionen können dies tun, ebenso wie Promise-Objekte.

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in den automatischen Executor der PHP-Coroutine Thunkify (Code). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen