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 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同
  • ¥50 如何openEuler 22.03上安装配置drbd
  • ¥20 ING91680C BLE5.3 芯片怎么实现串口收发数据
  • ¥15 无线连接树莓派,无法执行update,如何解决?(相关搜索:软件下载)
  • ¥15 Windows11, backspace, enter, space键失灵