Promesse inAWS SDK for PHPversione 3 - AWS SDK for PHP

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+.

Che 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 per l'implementazione delle promesse. Le promesse Guzzle supportano flussi di lavoro bloccanti e non bloccanti e possono essere utilizzate con qualsiasi loop di eventi non bloccanti.

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 DynamoDBDescribeTableoperazione.

$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

CommandPool fornisce un più potente meccanismo per l'esecuzione di più operazioni API simultaneamente.

Concatenamento di promesse

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.

Inoltro 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.

Annullamento di promesse

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.

Combinazione di promesse

È 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 su namespace-GuzzleHttp.Promise.

each e each_limit

Utilizza CommandPool in presenza di una coda di operazioni di comandi Aws\CommandInterface 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();