前提・実現したいこと
curl_multi_init
で並列してレスポンスを取得し、それを順次HTMLへ出力する方法を知りたいです。
宜しくお願い致します。
発生している問題・エラーメッセージ
curl_multi_init
で並列してレスポンスを取得する処理を実装したところなのですが、先の疑問が生じました。
これをHTMLに順次出力するにはどうしたらいいのか?という疑問です。
順次出力できないなら、せっかく並列で取得したレスポンスなのに、意味ないじゃん!と思ったのですが…方法が思いつきません。
該当のソースコード
例えば次のJSは、button
のクリックでPHPのsearch_all
が発動します。search_all
が複数のcURLを平行して実行するので、そのレスポンスを次のJSのresponse
で順次HTMLへ出力、ということをイメージしています。
jQeury
1$(document).on('click','button',function() { 2 $.ajax({ 3 url : 'http://www...', 4 type: 'POST', 5 data: { action: 'search_all' } 6 }).done( function( response ) { 7 // ここでPHPの search_all の結果を順次受け取り、HTMLに出力したい 8 }); 9});
次がsearch_all
になります。コメントでJSに返す
とあるところで、上記JSのresponseに返したいのですが…
PHP
1function search_all(){ 2 3 // curl_multiハンドラを用意 4 $TIMEOUT = 10; 5 $mh = curl_multi_init(); 6 7 // 送信データ 8 $data = array( 9 array( 'name' => 'a', 'data' => 1 ), 10 array( 'name' => 'b', 'data' => 2 ), 11 ); 12 13 // 送信データごとにcURLを実行 14 foreach ($data as $d) { 15 $ch = curl_init(); 16 curl_setopt_array($ch, array( 17 CURLOPT_URL => 'http://www...', 18 CURLOPT_RETURNTRANSFER => true, 19 CURLOPT_TIMEOUT => $TIMEOUT, 20 CURLOPT_CONNECTTIMEOUT => $TIMEOUT, 21 CURLOPT_HTTPHEADER => array('Content-Type: application/json'), 22 CURLOPT_CUSTOMREQUEST => 'POST', 23 CURLOPT_POSTFIELDS => json_encode($d, JSON_PRETTY_PRINT) 24 )); 25 curl_multi_add_handle($mh, $ch); 26 } 27 28 // リクエストを開始する 29 do { 30 $stat = curl_multi_exec($mh, $running); //multiリクエストスタート 31 } while ($stat === CURLM_CALL_MULTI_PERFORM); 32 33 // レスポンスをcurl_multi_selectで待つ 34 do switch (curl_multi_select($mh, $TIMEOUT)) { //イベントが発生するまでブロック 35 36 case -1: //selectに失敗 37 usleep(10); //ちょっと待ってからretry 38 do { 39 $stat = curl_multi_exec($mh, $running); 40 } while ($stat === CURLM_CALL_MULTI_PERFORM); 41 continue 2; 42 43 case 0: //タイムアウト 44 continue 2; //ここではcontinueでリトライ 45 46 default: //どれかが成功 or 失敗した 47 do { 48 $stat = curl_multi_exec($mh, $running); //ステータスを更新 49 } while ($stat === CURLM_CALL_MULTI_PERFORM); 50 51 do if ($raised = curl_multi_info_read($mh, $remains)) { 52 53 // JSに返す 54 $response = curl_multi_getcontent($raised['handle']); 55 if ($response === false) { 56 echo 'ERROR!!!'; 57 } else { 58 echo json_decode($response, true); 59 } 60 61 curl_multi_remove_handle($mh, $raised['handle']); 62 curl_close($raised['handle']); 63 } while ($remains); 64 65 } while ($running); 66 curl_multi_close($mh); 67}
試したこと
根本的に、一回のAJAXのリクエストで、「PHPの結果を順次JSに返す」ことなどできないだろう、という考えを持っています。
で結局、「PHPの結果を順次JSに返す」方法が思いつきませんので、ひとまずはcurl_multi_init
でなく普通のcurl_init
にして、jQeury側で以下のように非同期に複数実行し、順次その結果を出力していく手はずでできました。
jQeury
1function search_single(){ 2 // curl_initを実行する関数 3} 4 5var func = $.when( search_single() ).done( function( response ){ 6 // ここで順次HTMLに出力する 7}); 8funcs.push( func ); 9 10$.when.apply(null, funcs).then( 11 // 順次出力が全部終わったときの処理 12);
このように、まぁギリギリできましたので最悪これでもいいのですが、やはりcurl_multi_init
を使っての方法が気になっています。
それができなければ何のためのcURLの並列なのか?と疑問だからです。PHP側の処理は並列で早くはなりますが、結局HTMLへの出力がまとめて一回でしかできないのなら意味ないじゃん!っていう感じがします。
なのでcurl_multi_init
で並列してレスポンスを取得し、それを順次HTMLへ出力する方法を知りたい。となったのですが、いかがなものでしょうか。
補足情報(FW/ツールのバージョンなど)
なし
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/08/25 01:32
2020/08/25 01:33
2020/08/25 13:08
2020/08/25 13:35
2020/08/26 00:55
2020/08/26 00:55
2020/08/26 13:55 編集