songnuan 发表于 2015-07-14 09:58

PHP yield 异步操作结合同步业务代码例子

看了 PHPCon 2015 上海站司超的协程pdf有感而写的一小片段代码练练手,希望对大家了解yield有所帮助

代码<?php
/*
* yield 异步操作结合同步业务代码例子
* @author Corz<combo_k@126.com>
*/
//业务同步代码
function syncCode()
{
    var_dump((yield ['dns', 'www.baidu.com']));
    var_dump((yield ['lag', 200]));
    var_dump((yield ['dns', 'www.taobao.com']));
    var_dump((yield ['sql', 'show tables']));
}
//异步调用器
function asyncCaller(Generator $gen)
{
    $r = $gen->current();
    if (isset($r)) {
      switch ($r) {
            case 'sql':
                AsyncMysql::getInstance()->query($r,
                  function ($retval) use($gen) {
                        $gen->send($retval);
                        asyncCaller($gen);
                  });
                break;
            case 'dns':
                swoole_async_dns_lookup($r,
                  function ($host, $ip) use($gen) {
                        $gen->send([$host, $ip]);
                        asyncCaller($gen);
                  });
                break;
            case 'lag':
                swoole_timer_after($r,
                  function () use($gen, $r) {
                        $gen->send('lag ' . $r . 'ms');
                        asyncCaller($gen);
                  });
                break;
            default:
                $gen->send('no method');
                asyncCaller($gen);
                break;
      }
    }
}

asyncCaller(syncCode());

/**
* 异步mysql类
*/
class AsyncMysql
{

    /**
   * @var mysqli
   */
    protected $db = null;

    /**
   * @var callable
   */
    protected $callable = null;

    public static function getInstance()
    {
      static $instance = null;
      return isset($instance) ? $instance : ($instance = new self());
    }

    public function __construct()
    {
      $this->db = new mysqli('127.0.0.1', 'root', '123456', 'mysql');
      swoole_event_add(swoole_get_mysqli_sock($this->db), [$this, 'onQuery']);
    }

    public function onQuery($db_sock)
    {
      $res = $this->db->reap_async_query();
      call_user_func($this->callable, $res->fetch_all(MYSQLI_ASSOC));
    }

    /**
   * @param string    $sql
   * @param callable$callable
   */
    public function query($sql, callable $callable)
    {
      $this->callable = $callable;
      $this->db->query($sql, MYSQLI_ASYNC);
    }
}
页: [1]
查看完整版本: PHP yield 异步操作结合同步业务代码例子