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 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化