如果你有一批數據需要調用遠程接口處理,而遠程接口處理時間很長,比如需要1秒左右,那10條數據就是10秒,你的程序就要10S才能結束,而這樣的話一旦接口提供方有點問題,就需要20秒 30秒甚至更久,這樣就給我們帶來了極大隱患,雖然我們可以使用設置超時來避免這樣的長久等待,但是如果串行化不解決的話,程序始終是要長時間等所有任務都結束才能繼續判斷後面的結果的。
所以這裏引入異步概念,用 composer require spatie/async 安裝後的 Pool 裏面的create 和 async 以及await來解決問題。
例子如下:
我們接口提供方是這樣的代碼
<?php sleep(1); echo json_encode(range(1,15)); exit;
以往我們的調用是這樣的
foreach (range(1, 10) as $v) { $list[] = file_get_contents("http://localhost/index.php?act=" . $v); }
那就是按順序調用接口,統計下來耗時 10021 ms 也就是10秒
現在我們可以這樣做
<?php include "vendor/autoload.php"; use Spatie\Async\Pool; $pool = Pool::create(); foreach (range(1, 10) as $item) { $pool[] = async(function () use ($item) { return file_get_contents("http://localhost/index.php?act=" . $item); })->then(function (string $output) use(&$list) { $list[] = $output; }); } await($pool);
發現耗時 1341 ms,也就是說基本上是9-10個在同時並行請求,節省了很多時間。
我測試了一下如果不是在循環裏面調用接口,而是簡單的做一個item*2的數學運算,那同步可快多了,異步可慢多了。
<?php include "vendor/autoload.php"; use Spatie\Async\Pool; $pool = Pool::create(); foreach (range(1, 10) as $item) { $pool[] = async(function () use ($item) { return $item * 2; })->then(function (string $output) use(&$list) { $list[] = $output; }); } await($pool);
耗時 324 ms
而同步的嘛,只要 0.0019 ms
<?php foreach (range(1, 10) as $v) { $list[] = 2 * $v; }
畢竟這種情況下多餘的異步開銷反而不如同步啊。
適用場景就是多數據量,長耗時任務被阻塞等待,那這個時候用這個東西緩解一下壓力,提高一下速度還是不錯的。