2014-03-26 66 views
3

A.摘要如何在發送多個請求時將結果與請求進行匹配?

正如其標題,狂飲允許一次發送多個請求,以節省時間爲documentation

$responses = $client->send(array(
    $requestObj1, 
    $requestObj2, 
    ... 
)); 

(given that each request object is an instance of 
Guzzle\Http\Message\EntityEnclosingRequestInterface) 

當響應回來,以識別響應是針對哪個請求,我們可以通過每個請求循環和獲取響應(僅執行上述命令後可用):

$response1 = $requestObj1->getResponse(); 
$response2 = $requestObj2->getResponse(); 
... 

乙問題

如果請求對象包含相同的數據。無法確定原始請求。

假設我們有以下情形,我們需要創建2篇:距離服務器上的A和B:something.com/articles/create.json

每個請求具有相同的POST數據:

subject: This is a test article 

創建後,與2位置的狂飲反應回來:

something.com/articles/223.json 
something.com/articles/245.json 

用上面的方法來鏈接響應到其請求,我們仍然不知道哪個響應我s的文章,因爲請求對象是完全一樣的

因此,在我的數據庫,我不能寫下來的結果是:

article A -> Location: 245.json 
article B -> Location: 223.json 

因爲它可以角落找尋另一種方式:

article A -> Location: 223.json 
article B -> Location: 245.json 

一種解決方法是把一些額外的參數在POST請求,例如

subject: This is a test article 
record: A 

但是,距離服務器將返回錯誤,並不創建文章,因爲它不明白關鍵「記錄」。距離服務器是第三方服務器,我無法改變它的工作方式。

另一個適當的解決方案是在請求對象上設置一些特定的id/tag,以便我們可以在之後識別它。不過,我已經通過的文件看,但沒有方法來唯一地標識像

$request->setID("id1") 

or 

$request->setTag("id1") 

這已被竊聽我個月,仍要求能不能解決這個問題。

如果您有解決方案,請讓我知道。

許多非常感謝,你救了我!

感謝您閱讀這篇較長的文章。

+0

取決於用例,對於我使用域標識符的API。 –

回答

1

我發現了一個合適的方法來完成它,Guzzle允許在請求完成後添加回調。因此,我們可以通過在批

默認每個請求都可以像這樣

$request = $client->createRequest('GET', 'http://httpbin.org', [ 
    'headers' => ['X-Foo' => 'Bar'] 
]); 

創建設置它在每個請求實現這一那麼,要實現我們想要的:

$allRequests = []; 
$allResults = []; 

for($k=0; $k<=10; $k++){ 
    $allRequests['key_'.$k] = $client->createRequest('GET', 'http://httpbin.org?id='.$k, [ 
     'headers' => ['X-Foo' => 'Bar'], 
     'events' => [ 
      'complete' => function ($e) use (&$allResults, $k){ 
       $response = $e->getResponse(); 
       $allResults['key_'.$k] = $response->getBody().''; 
      } 
     ] 
    ]); 
} 

$client->sendAll(array_values($allRequests)); 

print_r($allResults); 

所以現在$ allResults對每個相應的請求都有結果。

例如$ allResults [ 'key_1']是$結果allRequests [ 'key_1']

1

我遇到同樣的問題。

我通過添加一個自定義查詢參數併爲每個請求生成一個唯一標識符並將其添加到請求url(您需要記住它們中的每一個以解決此問題)來解決此問題。

$responses = $client->send($requests)後,你可以通過響應迭代和檢索有效URL $response->getEffectiveUrl()並解析它(見parse_urlparse_str)來獲取自定義參數(含唯一ID)和你的哪一個具有它的請求數組中進行搜索。

0

我做這種方式:

// create your requests 
$requests[] = $client->createRequest('GET', '/endpoint', ['config' => ['order_id' => 123]]); 
... 
// in your success callback get 
$id = $event->getRequest()->getConfig()['order_id'] 
0

與新GuzzleHttp guzzlehttp更新/狂飲

併發/並行調用現在通過一些不同的方法執行,包括Promises .. Concurrent Requests

傳遞RequestInterfaces數組的舊方法將不再適用。

見例如這裏

$newClient = new \GuzzleHttp\Client(['base_uri' => $base]); 
    foreach($documents->documents as $doc){ 

     $params = [ 
      'language' =>'eng', 
      'text' => $doc->summary, 
      'apikey' => $key 
     ]; 

     $requestArr[$doc->reference] = $newClient->getAsync('/1/api/sync/analyze/v1?' . http_build_query($params)); 
    } 

    $time_start = microtime(true); 
    $responses = \GuzzleHttp\Promise\unwrap($requestArr); //$newClient->send($requestArr); 
    $time_end = microtime(true); 
    $this->get('logger')->error(' NewsPerf Dev: took ' . ($time_end - $time_start)); 

在這個例子中,你將可以參見各使用$ requestArr [$ doc->引用]的迴應的。簡而言之,給你的數組一個索引並運行Promise :: unwrap調用。

0

我發現了一個更好的答案。

我一次發送20個請求的批處理,同時發送4個請求,並使用池化技術完成,並拒絕回來,如文檔中所述。

我發現我可以添加此代碼到我的requestAsync()函數調用的結尾,當產生/建立數組(我在不同的地方)。

$request = $request->then(function (\GuzzleHttp\Psr7\Response $response) use ($source_db_object) { 
      $response->_source_object = $source_db_object; 
      return $response; 
}); 

然後在緩衝池中,我可以正常訪問響應中的_source_object,它工作的很好。 我覺得它有點古怪,但如果你確定使用一個永遠不會與Guzzle中的任何東西發生衝突的名字,這應該沒問題。