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);
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能
  • ¥15 jmeter脚本回放有的是对的有的是错的
  • ¥15 r语言蛋白组学相关问题
  • ¥15 Python时间序列如何拟合疏系数模型