关于jquery:在单个请求中使用JavaScript发送多个AJAX调用

Send multiple AJAX calls using JavaScript in a single request

我的网站上有一个页面,从https://hotelspro.com获取航班详细信息

输入航班详细信息后,我将收到大约400条不同的记录。问题是我必须循环每个记录,并发送单独的API请求以获取酒店信息。

我只能使用PHP或JavaScript。

使用PHP,它就像永远一样。我尝试了几种解决方案:

PHP - Solution 1: Using curl_exec()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$count = xxx; //Where xxx is the number of hotels
for ($i = 0; $i < $count; $i++) {
    $hotelCode = $json["results"][$i]["hotel_code"];
    $url ="http://cosmos.metglobal.tech/api/static/v1/hotels/" . $hotelCode ."/" ;

    $username = 'xxx';
    $password = 'xxx';
    $auth = base64_encode("$username:$password");

    $curl = curl_init();
    $data = array(
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING =>"",
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 0,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST =>"GET",
        CURLOPT_HTTPHEADER => array(
           "authorization: Basic $auth",
           "cache-control: no-cache",
            'Content-Length: 0'
        ),
    );

    curl_setopt_array($curl, $data);
    $response = curl_exec($curl);
    $err = curl_error($curl);
    curl_close($curl);

    $json = json_decode($response, true);
}

PHP - Solution 2: Using curl_multi_exec()

以下代码是从Stack Overflow上的答案中复制的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
$urls = array() ;
for ($i = 0; $i < $count; $i++) {
    $urls[] ="http://cosmos.metglobal.tech/api/static/v1/hotels/" . $json["results"][$i]["hotel_code"] ."/" ;
}

/* ********** Start Multi Threading ********** */
$active = 0 ;

// cURL multi-handle
$mh = curl_multi_init();

// This will hold cURLS requests for each file
$requests = array();

$options = array(
    CURLOPT_FOLLOWLOCATION  => true,
    CURLOPT_AUTOREFERER     => true,
    CURLOPT_HTTPHEADER      => array("Content-Type: application/json"),
    CURLOPT_SSL_VERIFYPEER  => false,
    CURLOPT_RETURNTRANSFER  => true,
    CURLOPT_USERPWD         =>"xxx:xxx"
);

foreach ($urls as $key => $url) {
    // Add initialized cURL object to array
    $requests[$key] = curl_init($url);

    // Set cURL object options
    curl_setopt_array($requests[$key], $options);

    // Add cURL object to multi-handle
    curl_multi_add_handle($mh, $requests[$key]);

    $active++;
}

// Do while all request have been completed
do {
   curl_multi_exec($mh, $active);
} while ($active > 0);

// Collect all data here and clean up
$j = 0 ;
foreach ($requests as $key => $request) {
    $result = curl_multi_getcontent($request); // Use this if you're not downloading into file, also remove CURLOPT_FILE option and fstreams array
    curl_multi_remove_handle($mh, $request); //assuming we're being responsible about our resource management
    curl_close($request);                    //being responsible again.  THIS MUST GO AFTER curl_multi_getcontent();

    $json["results"][$j]["hotel_details"] = json_decode($result, true) ;
    $j++ ;
}

curl_multi_close($mh);
/* ********** End Multi Threading ********** */

两个PHP解决方案需要花费大约1分钟来遍历所有记录。所以我现在尝试使用JavaScript同步请求发送请求。

JavaScript - Solution 1:

1
2
3
4
5
6
7
8
for (var i = 0; i < maxCount; i++) {
    var thisHotel = extJson.hotels.results[i] ;
    var hotelCode = thisHotel.hotel_code;

    $.get("/travel/hotel_pro_details/" + thisHotel.hotel_code, function (json) {  // /travel/hotel_pro_details/ is a function on my website that calls HotelsPro API
        //Code Handling Here
    }
}

上面的JavaScript解决方案也花了很多时间,但其中的积极之处在于,我可以在从API中获取结果后依次追加结果。

但我正在寻找一种更好的解决方案来减少加载时间。
由于我在JavaScript中循环记录,因此我无法立即发送所有记录并等待结果。

所以我的问题是:

有没有办法使用JavaScript,我可以在一个AJAX调用中发送多个记录,然后逐个处理所有回复?

谢谢...


如果你准备使用外部库,我想你可以考虑使用rxjs及其Observable模式,你可以使用它们的forkJoin方法同时发送所有$get个请求:

1
2
3
4
Rx.Observable.forkJoin(array)
  .subscribe(function(data) {
    /* data for all requests available here */
  }

演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$(document).ready(function() {
  // use your for loop to push() your requests into an array
  var array = [
    $.get('https://api.chucknorris.io/jokes/random'),
    $.get('https://api.chucknorris.io/jokes/random'),
    $.get('https://api.chucknorris.io/jokes/random'),
    $.get('https://api.chucknorris.io/jokes/random')
  ];

  // make all the http request at the same time
  Rx.Observable.forkJoin(array)
    .subscribe(function(data) {
      // Handle the response for each request individually
      $('body').append(data[0].value + '');
      $('body').append(data[1].value + '');
      $('body').append(data[2].value + '');
      $('body').append(data[3].value + '');
    })
});
1
2
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.7/rx.all.js">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">