dsgnze6572 2018-08-03 08:17
浏览 48
已采纳

使用cURL Multi,但仍然不是异步的

I use curl_multi to scrap several site, and I hope it will run asynchronously or parallel so it will not other to finish first.

I use jquery to trigger xmlhttprequest to php.

But what I get it still run synchronous, I dont know what is wrong whether my code or my PC specification (I run local server use core-i5 and 4GB memory)

This is my jquery code

function ajaxSearchFlight(agent)
{
    var depart_from = $("#depart_from").val();
    var arrive_to = $("#arrive_to").val();
    var depart_date = $("#depart_date").val();
    var adult = $("#adult").val();
    var child = $("#child").val();
    var infant = $("#infant").val();

    depart_date = new Date(depart_date);
    var year = depart_date.getFullYear();
    var month = depart_date.getMonth() + 1;
    var date = depart_date.getDate();
    if(month < 10)
    {
        month = "0"+month;
    }
    if(date < 10)
    {
        date = "0"+date;
    }
    depart_date = year+"-"+month+"-"+date;  

    if(agent == "all")
    {
        findflight_tesflight1(depart_from, arrive_to, depart_date, adult, child, infant);
        findflight_tesflight2(depart_from, arrive_to, depart_date, adult, child, infant);
    }
}

function findflight_tesflight1(depart_from, arrive_to, depart_date, adult, child, infant)
{
    var xhr = new XMLHttpRequest();
    xhr.open('GET', '<?php echo Url::toRoute("flight/getliveflighttesflight1"); ?>?depart_from='+depart_from+'&arrive_to='+arrive_to+'&date_format_start='+depart_date+'&adults_pass='+adult+'&children_pass='+child+'&infants_pass='+infant, true);

    xhr.onreadystatechange = function() {
        if(this.readyState == 4) 
        {
            if(this.status == 200)
            {
                var data = JSON.parse(this.responseText);   
            }
        }
    };

    xhr.send(); 
}

function findflight_tesflight2(depart_from, arrive_to, depart_date, adult, child, infant)
{       
    var xhr = new XMLHttpRequest();
    xhr.open('GET', '<?php echo Url::toRoute("flight/getliveflighttesflight2"); ?>?depart_from='+depart_from+'&arrive_to='+arrive_to+'&date_format_start='+depart_date+'&adults_pass='+adult+'&children_pass='+child+'&infants_pass='+infant, true);

    xhr.onreadystatechange = function() {
        if(this.readyState == 4) 
        {
            if(this.status == 200)
            {
                var data = JSON.parse(this.responseText);
            }
        }
    };

    xhr.send(); 
}

and this is PHP code

class FlightController extends \yii\web\Controller
{   
    protected $mh;

    public function beforeAction($event)
    {
        $this->mh = curl_multi_init();
        return parent::beforeAction($event);
    }   

    public function actionGetliveflighttesflight1($depart_from, $arrive_to, $date_format_start, $adult, $child, $infant)
    {               
        $url = 'https://api.flight2.com/en/flight/';                        

        $response_tes = "";
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);    

        curl_multi_add_handle($this->mh,$ch);

        do {
            while(($execrun = curl_multi_exec($this->mh, $running)) == CURLM_CALL_MULTI_PERFORM);
            if($execrun != CURLM_OK)
                break;
            while($done = curl_multi_info_read($this->mh)) {
                $info = curl_getinfo($done['handle']);
                if ($info['http_code'] == 200)  {
                    $output = curl_multi_getcontent($done['handle']);
                    $response_tes = $output;
                    curl_multi_remove_handle($this->mh, $done['handle']);
                } else {
                }
            }
        } while ($running);     

        try {
            return $response_tes;
        } catch (Exception $e) {            
        }               
    }

    public function actionGetliveflighttesflight2($depart_from, $arrive_to, $date_format_start, $adult, $child, $infant)    
    {                   
        $url = 'https://www.flight1.com/ajax?d='.$depart_from.'&a='.$arrive_to.'&date='.$date_format_start.'&adult='.$adult.'&child='.$child.'&infant='.$infant;                    

        $response_tes = "";
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_ENCODING, 'gzip'); 

        curl_multi_add_handle($this->mh,$ch);

        do {
            while(($execrun = curl_multi_exec($this->mh, $running)) == CURLM_CALL_MULTI_PERFORM);
            if($execrun != CURLM_OK)
                break;
            while($done = curl_multi_info_read($this->mh)) {
                $info = curl_getinfo($done['handle']);
                if ($info['http_code'] == 200)  {
                    $output = curl_multi_getcontent($done['handle']);
                    $response_tes = $output;
                    curl_multi_remove_handle($this->mh, $done['handle']);
                } else {
                }
            }
        } while ($running);         

        try {       
            return $response_tes;   
        } catch (Exception $e) {            
        }       
    }
}

Please help, I need to make it async.

  • 写回答

1条回答 默认 最新

  • drq61040 2018-08-03 08:34
    关注

    You have it set up right kinda, but your logic is wrong. It looks like your only ever sending information to your php scripts for one url at a time. You might as well just use a regular curl request.

    Curl_multi is designed to fetch the data for multiple urls asynchronously. So that being said, you will want to feed the functions multiple urls.

    So here is an example of how to set up a good curl_multi routine. You will have to adapt this to your own code, but it's a good road map. Hope it helps.

    function multi_thread_curl($urlArray, $optionArray, $nThreads) {
    
      //Group your urls into groups/threads.
      $curlArray = array_chunk($urlArray, $nThreads, $preserve_keys = true);
    
      //Iterate through each batch of urls.
      foreach($curlArray as $threads) {
    
          //Create your cURL resources.
          foreach($threads as $key=>$value) {
    
          ${ch . $key} = curl_init();
    
            curl_setopt_array(${ch . $key}, $optionArray); //Set your main curl options.
            curl_setopt(${ch . $key}, CURLOPT_URL, $value); //Set url.
    
            }
    
          //Create the multiple cURL handler.
          $mh = curl_multi_init();
    
          //Add the handles.
          foreach($threads as $key=>$value) {
    
          curl_multi_add_handle($mh, ${ch . $key});
    
          }
    
          $active = null;
    
          //execute the handles.
          do {
    
          $mrc = curl_multi_exec($mh, $active);
    
          } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    
          while ($active && $mrc == CURLM_OK) {
    
              if (curl_multi_select($mh) != -1) {
                  do {
    
                      $mrc = curl_multi_exec($mh, $active);
    
                  } while ($mrc == CURLM_CALL_MULTI_PERFORM);
              }
    
          }
    
          //Get your data and close the handles.
          foreach($threads as $key=>$value) {
    
          $results[$key] = curl_multi_getcontent(${ch . $key});
    
          curl_multi_remove_handle($mh, ${ch . $key});
    
          }
    
          //Close the multi handle exec.
          curl_multi_close($mh);
    
      }
    
    
      return $results;
    
    }
    
    
    //Add whatever options here. The CURLOPT_URL is left out intentionally.
    //It will be added in later from the url array.  
    $optionArray = array(
    
      CURLOPT_SSL_VERIFYPEER    => FALSE,
      CURLOPT_RETURNTRANSFER    => TRUE,
      CURLOPT_TIMEOUT           => 10
    
    );
    
    //Create an array of your urls.
    $urlArray = array(
    
     'www.example.com/index.php?id=1',
     'www.example.com/index.php?id=2',
     'www.example.com/index.php?id=3',
     'www.example.com/index.php?id=4'
    
    );
    
    //Play around with this number and see what works best.
    //This is how many urls it will try to do at one time.
    $nThreads = 20;  
    
    
    $results = multi_thread_curl($urlArray, $optionArray, $nThreads);
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 刚接触VFP,我想知道为什么是这种情况,有人可以看看吗
  • ¥15 io.jsonwebtoken.security.Keys
  • ¥15 急,ubuntu安装后no caching mode page found等
  • ¥15 联想交换机NE2580O/NE1064TO安装SONIC
  • ¥15 防火墙的混合模式配置
  • ¥15 Ubuntu不小心注销了要怎么恢复啊
  • ¥15 win10电脑安装完plcsim advanced4.0运行时为什么会提示找不到虚拟网卡
  • ¥15 安装powerbuilder10卡在安装程序正在运行这个页面 没有下一步任何指令
  • ¥15 关于mpi的问题:请问遇到这种情况需要怎么解决,出现这个问题后电脑不能进行mpi多核运行只能进行单核运行
  • ¥50 微信聊天记录备份到电脑提示成功了,但还是没同步到电脑微信