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

报告相同问题?

悬赏问题

  • ¥50 滴滴出行模拟系统,模拟叫车、出行过程等过程
  • ¥15 信号发生器如何将频率调大,步尽值改成10
  • ¥15 keil 5 编程智能家具,风扇台灯开关,人体感应等
  • ¥100 找一名渗透方面的专家
  • ¥20 使用Matlab gui设计一个插补小程序
  • ¥15 evo评估时曲线出现问题
  • ¥15 eNSP拓扑图配置实验
  • ¥20 有没有兄弟会替换fmod studio的.bank文件内的音效?
  • ¥20 如何解决访问网址被屏蔽的情况
  • ¥20 powerbuilder datawindow控件导出Excel数据,可不可以不自动覆盖原数据,而是在后面新插入入数据。