Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
Promesse inAWS SDK for PHPVersione 3
AWS SDK for PHP utilizza promesse per consentire flussi di lavoro asincroni e, a sua volta, questa asincronicità consente l'invio simultaneo di richieste HTTP. La specifica per le promesse utilizzata da SDK è Promises/A+
Cos'è una promessa?
Una promessa rappresenta l'eventuale risultato di un'operazione asincrona. La modalità principale di interazione con una promessa è attraverso il metodo then
. Questo metodo registra callback per ricevere l'eventuale valore di una promessa o il motivo per cui la promessa non può essere soddisfatta.
AWS SDK for PHP si basa sul pacchetto Composer guzzlehttp/promises
Nota
Le richieste HTTP vengono inviate simultaneamente in AWS SDK for PHP utilizzando un singolo thread, in cui chiamate non bloccanti vengono utilizzate per trasferire una o più richieste HTTP e, allo stesso tempo, reagire a modifiche di stato (ad esempio, soddisfare o respingere promesse).
Promesse in SDK
Le promesse vengono utilizzate in tutto il kit SDK. Ad esempio, le promesse vengono utilizzate nella maggior parte delle astrazioni di alto livello fornite da SDK: impaginatori, waiter, pool di comandi, caricamenti in più parti, trasferimenti tra directory S3 e bucket e così via.
Tutti i client che SDK fornisce restituiscono promesse quando si invoca uno qualsiasi dei metodi con suffisso Async
. Ad esempio, il codice seguente mostra come creare una promessa per ottenere i risultati di un Amazon DynamoDBDescribeTable
operazione.
$client = new Aws\DynamoDb\DynamoDbClient([ 'region' => 'us-west-2', 'version' => 'latest', ]); // This will create a promise that will eventually contain a result $promise = $client->describeTableAsync(['TableName' => 'mytable']);
Nota: è possibile è effettuare una chiamata a describeTable
o a describeTableAsync
. Questi metodi sono metodi magici __call
su un client supportati dal modello di API e dal numero version
associati al client. Chiamando metodi quali describeTable
senza il suffisso Async
, il client presenterà un blocco mentre invia una richiesta HTTP e restituirà un oggetto Aws\ResultInterface
o genererà una Aws\Exception\AwsException
. Aggiungendo al nome dell'operazione il suffisso Async
(ad esempio, describeTableAsync
), il client creerà una promessa che verrà soddisfatta con un oggetto Aws\ResultInterface
o rifiutata con una Aws\Exception\AwsException
.
Importante
Quando la promessa viene restituita, il risultato potrebbe essere già arrivato (ad esempio, quando si utilizza un gestore fittizio), oppure la richiesta HTTP potrebbe non essere stata avviata.
È possibile registrare un callback con la promessa utilizzando il metodo then
. Questo metodo accetta due callback, $onFulfilled
e $onRejected
, entrambi opzionali. Il callback $onFulfilled
viene invocato se la promessa viene soddisfatta, mentre il callback $onRejected
viene invocato se la promessa viene respinta (ovvero ha esito negativo).
$promise->then( function ($value) { echo "The promise was fulfilled with {$value}"; }, function ($reason) { echo "The promise was rejected with {$reason}"; } );
Esecuzione di comandi simultanei
È possibile comporre più promesse insieme in modo che vengano eseguite simultaneamente. A tal fine, è possibile integrare SDK con un loop di eventi non bloccante, oppure creare più promesse e attenderne il completamento simultaneo.
use GuzzleHttp\Promise; $sdk = new Aws\Sdk([ 'version' => 'latest', 'region' => 'us-west-2' ]); $s3 = $sdk->createS3(); $ddb = $sdk->createDynamoDb(); $promises = [ 'buckets' => $s3->listBucketsAsync(), 'tables' => $ddb->listTablesAsync(), ]; // Wait on both promises to complete and return the results $results = Promise\unwrap($promises); // Notice that this method will maintain the input array keys var_dump($results['buckets']->toArray()); var_dump($results['tables']->toArray());
Nota
LaCommandPoolfornisce un più potente meccanismo per l'esecuzione di più operazioni API simultaneamente.
Concaten
Uno degli aspetti migliori delle promesse è il fatto che sono componibili, per cui consentono di creare pipeline di trasformazione.. Le promesse vengono composte concatenando callback then
con callback then
successivi. Il valore restituito da un metodo then
è una promessa che viene soddisfatta o respinta in base al risultato dei callback forniti.
$promise = $client->describeTableAsync(['TableName' => 'mytable']); $promise ->then( function ($value) { $value['AddedAttribute'] = 'foo'; return $value; }, function ($reason) use ($client) { // The call failed. You can recover from the error here and // return a value that will be provided to the next successful // then() callback. Let's retry the call. return $client->describeTableAsync(['TableName' => 'mytable']); } )->then( function ($value) { // This is only invoked when the previous then callback is // fulfilled. If the previous callback returned a promise, then // this callback is invoked only after that promise is // fulfilled. echo $value['AddedAttribute']; // outputs "foo" }, function ($reason) { // The previous callback was rejected (failed). } );
Nota
Il valore restituito dal callback di una promessa è l'argomento $value
che viene fornito a promesse in downstream. Se si desidera fornire un valore per eseguire il downstream di catene di promesse, è necessario restituire un valore nella funzione di callback.
Inololtro di rifiuto
È possibile registrare un callback da invocare quando una promessa viene respinta. Se viene generata un'eccezione in un callback, la promessa viene respinta con quell'eccezione e le promesse successive nella catena vengono rifiutate con quell'eccezione. Se si restituisce correttamente un valore da un callback $onRejected
, le promesse successive nella catena vengono soddisfatte con il valore restituito dal callback $onRejected
.
Attesa di promesse
È possibile forzare il completamento sincrono di una promessa utilizzando il metodo wait
della promessa.
$promise = $client->listTablesAsync(); $result = $promise->wait();
Se si presenta un'eccezione durante l'invocazione della funzione wait
di una promessa, la promessa viene respinta con l'eccezione e l'eccezione viene sollevata.
use Aws\Exception\AwsException; $promise = $client->listTablesAsync(); try { $result = $promise->wait(); } catch (AwsException $e) { // Handle the error }
La chiamata della funzione wait
su una promessa che è stata soddisfatta non attiva la funzione di attesa. Restituisce semplicemente il valore distribuito in precedenza.
$promise = $client->listTablesAsync(); $result = $promise->wait(); assert($result ### $promise->wait());
La chiamata della funzione wait
su una promessa che è stata respinta genera un'eccezione. Se il motivo del rifiuto è un'istanza di \Exception
, il motivo viene generato. Altrimenti, viene generato GuzzleHttp\Promise\RejectionException
e il motivo può essere ottenuto chiamando il metodo getReason
dell'eccezione.
Nota
Le chiamate relative a operazioni API in AWS SDK for PHP vengono rifiutate con sottoclassi della classe Aws\Exception\AwsException
. Tuttavia, è possibile che il motivo distribuito a un metodo then
sia diverso per via dell'aggiunta di un middleware personalizzato che modifica il motivo del rifiuto.
Annulluspmise
Le promesse possono essere annullate utilizzando il metodo cancel()
di una promessa. Se una promessa è stata già risolta , chiamare cancel()
non avrà alcun effetto. L'annullamento di una promessa determina l'annullamento anche delle promesse in attesa di distribuzione dalla promessa. Una promessa annullata viene respinta con GuzzleHttp\Promise\RejectionException
.
Combinbinen
È possibile combinare promesse in forma aggregata per creare flussi di lavoro più sofisticati. Il pacchetto guzzlehttp/promise
contiene varie funzioni che è possibile utilizzare per combinare promesse.
È possibile trovare la documentazione dell'API per tutte le funzioni di raccolta di promesse suspazio dei nomi-GuzzleHttp.Promise.
each e each_limit
Utilizzo dell'CommandPoolquando hai una coda di attività diAws\CommandInterface
comandi da eseguire simultaneamente con un pool di dimensioni fisse (i comandi possono essere in memoria o generati da un'iterazione lazy). CommandPool
garantisce che un numero fisso di comandi venga inviato simultaneamente fino a esaurimento dell'iterazione fornita.
CommandPool
funziona solo con comandi eseguiti dal client stesso. È possibile utilizzare la funzione GuzzleHttp\Promise\each_limit
per eseguire l'invio di comandi di diversi client simultaneamente utilizzando un pool di dimensioni fisse.
use GuzzleHttp\Promise; $sdk = new Aws\Sdk([ 'version' => 'latest', 'region' => 'us-west-2' ]); $s3 = $sdk->createS3(); $ddb = $sdk->createDynamoDb(); // Create a generator that yields promises $promiseGenerator = function () use ($s3, $ddb) { yield $s3->listBucketsAsync(); yield $ddb->listTablesAsync(); // yield other promises as needed... }; // Execute the tasks yielded by the generator concurrently while limiting the // maximum number of concurrent promises to 5 $promise = Promise\each_limit($promiseGenerator(), 5); // Waiting on an EachPromise will wait on the entire task queue to complete $promise->wait();
Co-routine delle promesse
Una delle caratteristiche più potenti della libreria di promesse Guzzle è il fatto che consente di utilizzare co-routine delle promesse che rendono la scrittura di flussi di lavoro asincroni più simile alla scrittura di tradizionali flussi di lavoro sincroni. E, in effetti, AWS SDK for PHP utilizza co-routine delle promesse nella maggior parte delle astrazioni di alto livello.
Si immagini di creare diversi bucket e di caricare un file nel bucket quando quest'ultimo diventa disponibile, il tutto simultaneamente, in modo che l'operazione venga eseguita nel minor tempo possibile. È possibile eseguire questa operazione in modo semplice combinando più co-routine utilizzando la funzione delle promesse all()
.
use GuzzleHttp\Promise; $uploadFn = function ($bucket) use ($s3Client) { return Promise\coroutine(function () use ($bucket, $s3Client) { // You can capture the result by yielding inside of parens $result = (yield $s3Client->createBucket(['Bucket' => $bucket])); // Wait on the bucket to be available $waiter = $s3Client->getWaiter('BucketExists', ['Bucket' => $bucket]); // Wait until the bucket exists yield $waiter->promise(); // Upload a file to the bucket yield $s3Client->putObjectAsync([ 'Bucket' => $bucket, 'Key' => '_placeholder', 'Body' => 'Hi!' ]); }); }; // Create the following buckets $buckets = ['foo', 'baz', 'bar']; $promises = []; // Build an array of promises foreach ($buckets as $bucket) { $promises[] = $uploadFn($bucket); } // Aggregate the promises into a single "all" promise $aggregate = Promise\all($promises); // You can then() off of this promise or synchronously wait $aggregate->wait();