在 PHP 專案使用 Guzzle 發送異步 HTTP 請求

異步請求

使用 GuzzleHttp\Client 類別的 requestAsync() 方法來建立異步請求(async requests)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$results = [];

$client = new \GuzzleHttp\Client();

$uri = 'https://jsonplaceholder.typicode.com/todos';

$promise = $client->requestAsync('GET', $uri);

$promise->then(
function (\Psr\Http\Message\ResponseInterface $res) use (&$results) {
$results[] = json_decode($res->getBody(), true);
},
function (\GuzzleHttp\Exception\RequestException $e) {
echo $e->getMessage() . "\n";
echo $e->getRequest()->getMethod();
}
);

$promise->wait();

echo 'results: '.count($results)."\n";

結果:

1
results: 1

平行請求

使用 Promise 和異步請求同時發送多個請求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$results = [];

$client = new \GuzzleHttp\Client();

$uri = 'https://jsonplaceholder.typicode.com/todos';

$promise = function ($i) use ($client, $uri) {
echo $i.': '.date('H:i:s')."\n";

return $client->getAsync($uri);
};

$promises = [
'1' => $promise(1),
'2' => $promise(2),
'3' => $promise(3),
'4' => $promise(4),
'5' => $promise(5),
];

$results = \GuzzleHttp\Promise\unwrap($promises);

echo 'results: '.count($results);

結果:

1
2
3
4
5
6
1: 15:58:10
2: 15:58:10
3: 15:58:10
4: 15:58:10
5: 15:58:10
results: 5

當發送不確定數量的請求時,使用 GuzzleHttp\Pool 類別。

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
$results = [];

$client = new \GuzzleHttp\Client();

$requests = function ($total) use ($client) {
$uri = 'https://jsonplaceholder.typicode.com/todos';

for ($i = 0; $i < $total; $i++) {
echo $i.': '.date('H:i:s')."\n";

yield function() use ($client, $uri) {
return $client->getAsync($uri);
};
}
};

$pool = new \GuzzleHttp\Pool($client, $requests(10), [
'concurrency' => 10,
'fulfilled' => function ($response, $index) use (&$results) {
$results[] = json_decode($response->getBody(), true);
},
'rejected' => function ($reason, $index) {
// this is delivered each failed request
},
]);

// Initiate the transfers and create a promise
$promise = $pool->promise();

// Force the pool of requests to complete.
$promise->wait();

echo 'results: '.count($results)."\n";

平行數設為 10,結果:

1
2
3
4
5
6
7
8
9
10
11
0: 15:34:23
1: 15:34:23
2: 15:34:23
3: 15:34:23
4: 15:34:23
5: 15:34:23
6: 15:34:23
7: 15:34:23
8: 15:34:23
9: 15:34:23
results: 10

平行數設為 1,結果:

1
2
3
4
5
6
7
8
9
10
11
0: 15:35:54
1: 15:35:55
2: 15:35:57
3: 15:35:58
4: 15:35:59
5: 15:35:59
6: 15:36:00
7: 15:36:00
8: 15:36:01
9: 15:36:01
results: 10

程式碼

參考資料