[php]利用curl_multi_exec和yield实现异步

Yield参照鸟哥的博客:http://www.laruence.com/2015/05/28/3038.html
这里的异步是将curl的请求发送,然后控制权交还给php,直到最后期中获取curl后的结果。程序如下:

    public function async() {
        
        $start = microtime(true);
        $url = "http://waimai.baidu.com/waimai?qt=poisug";  //随意的一个接口
        $i = 50; //假设请求N次
        do {
            $gen[$i] = $this->_request($url);
            //实际应用中可能在多次请求之间有其他事情要处理,否则我们可以直接使用curl_multi
            //suppose i can do something here
            $i --; 
        }while($i);
        
        $ret = $this->_dealGen($gen);
        var_dump($ret);
        $end = microtime(true);
        echo $end - $start;
        
    }
      
    protected function _request($url) {
        
        $mh = curl_multi_init();       
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);      
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_MAXREDIRS, 7);
        curl_multi_add_handle($mh, $ch);
        do {
            $mrc = curl_multi_exec($mh, $active);
			//可以看到很多参考代码这里是sleep(),其实浪费了程序执行的时间
            yield null;  //先去请求,不用等待结果
        } while ($active > 0); 
        
        $raw = curl_multi_getcontent($ch);
        curl_multi_remove_handle($mh, $ch);
        curl_multi_close($mh);
        yield $raw;       
    }
    
    protected function _dealGen($gens) {
             
        $ret = array();
        do {
            $running = false;
            foreach ($gens as $id => $gen) {              
                if ($gen->valid()) {
                    //有任意没处理完的yield就继续进行处理
                    $running = true;
                    $gen->next();
                    $tmp = $gen->current();
                    if ($tmp !== null) {
                        $ret[$id] = $tmp;
                    }
                }
            }
        } while ($running);       
        return $ret;          
    }

当然主要是接口比较给力,这里只用了0.15260910987854毫秒。可见是进行异步处理的结果。