

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Programação assíncrona usando a versão 3 AWS SDK para PHP
<a name="asynchronous-requests"></a>

Você pode enviar comandos simultaneamente usando os recursos assíncronos do SDK. Você pode enviar solicitações de forma assíncrona colocando o sufixo `Async` no nome de uma operação. Isso inicia a solicitação e retorna uma promessa. 

A promessa é preenchida com o objeto do resultado em caso de êxito ou rejeitada com uma exceção em caso de falha. Isso permite criar várias promessas e fazer com que elas enviem solicitações HTTP simultaneamente quando o manipulador HTTP subjacente transfere as solicitações.

 **Importações** 

```
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
```

 **Código de exemplo** 

```
// Create an SDK class used to share configuration across clients.
$sdk = new Aws\Sdk([
    'region'   => 'us-west-2'
]);
// Use an Aws\Sdk class to create the S3Client object.
$s3Client = $sdk->createS3();
//Listing all S3 Bucket
$CompleteSynchronously = $s3Client->listBucketsAsync();
// Block until the result is ready.
$CompleteSynchronously = $CompleteSynchronously->wait();
```

Você pode forçar uma promessa a concluir de forma síncrona usando o método `wait` da promessa. Forçar a promessa a ser concluída também "decodifica" o estado da promessa por padrão, o que significa que ela retornará o resultado da promessa ou gerará a exceção encontrada. Ao chamar `wait()` em uma promessa, o processo é bloqueado até que a solicitação HTTP seja concluída e o resultado seja preenchido ou que uma exceção seja gerada.

Ao usar o SDK com uma biblioteca de loop de eventos, não bloqueie os resultados. Em vez disso, use o método `then()` de um resultado para acessar uma promessa que é resolvida ou rejeitada quando a operação é concluída.

 **Importações** 

```
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
```

 **Código de exemplo** 

```
// Create an SDK class used to share configuration across clients.
$sdk = new Aws\Sdk([
    'region'   => 'us-west-2'
]);
// Use an Aws\Sdk class to create the S3Client object.
$s3Client = $sdk->createS3();
```

```
$promise = $s3Client->listBucketsAsync();
$promise
    ->then(function ($result) {
        echo 'Got a result: ' . var_export($result, true);
    })
    ->otherwise(function ($reason) {
        echo 'Encountered an error: ' . $reason->getMessage();
    });
```

# Promessas no AWS SDK para PHP versão 3
<a name="guide_promises"></a>

O AWS SDK para PHP usa **promessas** para permitir fluxos de trabalho assíncronos, e essa capacidade de assincronia permite que as solicitações HTTP sejam enviadas simultaneamente. A especificação da promessa usada pelo SDK é [Promises/A\$1](https://promisesaplus.com/).

## O que é uma promessa?
<a name="what-is-a-promise"></a>

Uma *promessa* representa o resultado eventual de uma operação assíncrona. A principal maneira de interagir com uma promessa é por meio de seu método `then`. Esse método registra retornos de chamada para receber o valor eventual de uma promessa ou o motivo pelo qual a promessa não pode ser cumprida.

O AWS SDK para PHP depende do pacote do Composer [guzzlehttp/promises](https://github.com/guzzle/promises) para a implementação de suas promessas. As promessas do Guzzle oferecem suporte a fluxos de trabalho com e sem bloqueios e podem ser usadas com qualquer loop de eventos sem bloqueios.

**nota**  
As solicitações HTTP são enviadas simultaneamente no AWS SDK para PHP usando um único thread, no qual as chamadas sem bloqueio são usadas para transferir uma ou mais solicitações HTTP e, ao mesmo tempo, reagir a alterações de estado (por exemplo, cumprindo ou rejeitando promessas).

## Promessas no SDK
<a name="promises-in-the-sdk"></a>

As promessas são usadas em todo o SDK. Por exemplo, as promessas são usadas na maioria das abstrações de alto nível fornecidas pelo SDK: [paginadores](guide_paginators.md#async-paginators), [waiters](guide_waiters.md#async-waiters), [grupos de comandos](guide_commands.md#command-pool), [multipart uploads](s3-multipart-upload.md), [transferências de diretórios/buckets do S3](s3-transfer.md) etc.

Todos os clientes que o SDK fornece retornam promessas quando você chama qualquer um dos métodos com o sufixo `Async`. Por exemplo, o código a seguir mostra como criar uma promessa para obter os resultados de uma operação `DescribeTable` do Amazon DynamoDB.

```
$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']);
```

Observe que você pode chamar `describeTable` ou `describeTableAsync`. Esses métodos são métodos `__call` mágicos em um cliente, que são acionados pelo modelo da API e pelo número da `version` associada ao cliente. Chamando métodos como `describeTable` sem o sufixo `Async`, o cliente será bloqueado ao enviar uma solicitação HTTP e retornar um objeto `Aws\ResultInterface` ou gerar uma `Aws\Exception\AwsException`. Com o uso do sufixo `Async` no nome da operação (isto é, `describeTableAsync`), o cliente criará uma promessa que será eventualmente cumprida com um objeto `Aws\ResultInterface` ou rejeitada com uma `Aws\Exception\AwsException`.

**Importante**  
Quando a promessa é retornada, o resultado pode já ter chegado (por exemplo, ao usar um manipulador simulado) ou a solicitação HTTP pode não ter sido iniciada.

Você pode registrar um retorno de chamada com a promessa usando o método `then`. Esse método aceita dois retornos de chamada, `$onFulfilled` e `$onRejected`, que são opcionais. O retorno de chamada `$onFulfilled` será invocado se a promessa for cumprida, e o retorno de chamada `$onRejected` será invocado se a promessa for rejeitada (o que significa que falhou).

```
$promise->then(
    function ($value) {
        echo "The promise was fulfilled with {$value}";
    },
    function ($reason) {
        echo "The promise was rejected with {$reason}";
    }
);
```

### Execução simultânea de comandos
<a name="executing-commands-concurrently"></a>

Várias promessas podem ser compostas em conjunto, para que sejam executadas simultaneamente. Isso pode ser obtido integrando o SDK com um loop de eventos sem bloqueio ou acumulando várias promessas e aguardando que sejam concluídas simultaneamente.

```
use GuzzleHttp\Promise\Utils;

$sdk = new Aws\Sdk([
    'version' => 'latest',
    'region'  => 'us-east-1'
]);

$s3 = $sdk->createS3();
$ddb = $sdk->createDynamoDb();

$promises = [
    'buckets' => $s3->listBucketsAsync(),
    'tables'  => $ddb->listTablesAsync(),
];

// Wait for both promises to complete.
$results = Utils::unwrap($promises);

// Notice that this method will maintain the input array keys.
var_dump($results['buckets']->toArray());
var_dump($results['tables']->toArray());
```

**nota**  
O [CommandPool](guide_commands.md#command-pool) fornece um mecanismo mais poderoso para executar várias operações de API simultaneamente.

## Encadeamento de promessas
<a name="chaining-promises"></a>

Um dos melhores aspectos das promessas é que elas podem ser compostas permitindo que você crie pipelines de transformação. Promessas são compostas pelo encadeamento de retornos de chamada `then` com retornos de chamada `then` subsequentes. O valor do retorno de um método `then` é uma promessa que é cumprida ou rejeitada com base no resultado dos retornos de chamada fornecidos.

```
$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**  
O valor do retorno de chamada de uma promessa é o argumento `$value` que é fornecido para promessas de downstream. Para fornecer um valor para cadeias de promessas de downstream, você deve retornar um valor na função de retorno de chamada.

### Encaminhamento de rejeição
<a name="rejection-forwarding"></a>

Você pode registrar um retorno de chamada a ser invocado quando uma promessa for rejeitada. Se uma exceção for gerada em qualquer retorno de chamada, a promessa será rejeitada com a exceção, e as próximas promessas na cadeia serão rejeitadas com a exceção. Se você retornar um valor de um retorno de chamada `$onRejected` com êxito, as próximas promessas na cadeia de promessas serão cumpridas com o valor da chamada de retorno `$onRejected`.

## Espera por promessas
<a name="waiting-on-promises"></a>

Você pode forçar a conclusão de promessas de forma síncrona usando o método `wait` da promessa.

```
$promise = $client->listTablesAsync();
$result = $promise->wait();
```

Se uma exceção for encontrada ao invocar a função `wait` de uma promessa, a promessa será rejeitada com a exceção, e a exceção será gerada.

```
use Aws\Exception\AwsException;

$promise = $client->listTablesAsync();

try {
    $result = $promise->wait();
} catch (AwsException $e) {
    // Handle the error
}
```

Chamar `wait` em uma promessa que foi cumprida não aciona a função de espera. Ela simplesmente retorna o valor fornecido anteriormente.

```
$promise = $client->listTablesAsync();
$result = $promise->wait();
assert($result ### $promise->wait());
```

Chamar `wait` em uma promessa que foi rejeitada gera uma exceção. Se o motivo da rejeição for uma instância de `\Exception`, o motivo será gerado. Caso contrário, uma `GuzzleHttp\Promise\RejectionException` será gerada e o motivo poderá ser obtido chamando o método `getReason` da exceção.

**nota**  
As chamadas de operações da API no AWS SDK para PHP são rejeitadas com subclasses da classe `Aws\Exception\AwsException`. No entanto, é possível que o motivo fornecido a um método `then` seja diferente porque a adição de um middleware personalizado altera o motivo de uma rejeição.

## Cancelamento de promessas
<a name="canceling-promises"></a>

Promessas podem ser canceladas usando o método `cancel()` de uma promessa. Se uma promessa já tiver sido resolvida, a chamada de `cancel()` não terá nenhum efeito. O cancelamento de uma promessa cancela a promessa e todas as promessas que estão aguardando a entrega da promessa. Uma promessa cancelada é rejeitada com uma `GuzzleHttp\Promise\RejectionException`.

## Combinação de promessas
<a name="combining-promises"></a>

Você pode combinar promessas em promessas agregadas para criar fluxos de trabalho mais sofisticados. O pacote `guzzlehttp/promise` contém várias funções que podem ser usadas para combinar promessas.

É possível encontrar a documentação da API de todas as funções da coleção de promessas em [namespace-GuzzleHttp.Promise](https://docs.aws.amazon.com/aws-sdk-php/v3/api/namespace-GuzzleHttp.Promise.html).

### each e each\$1limit
<a name="each-and-each-limit"></a>

Use o [CommandPool](guide_commands.md#command-pool) quando tiver uma fila de tarefas de comandos `Aws\CommandInterface` para execução simultânea com um tamanho de grupo fixo (os comandos podem estar na memória ou serem gerados por um iterador lento). O `CommandPool` garante que um número fixo de comandos sejam enviados simultaneamente até que o iterador fornecido esteja esgotado.

O `CommandPool` funciona apenas com comandos que são executados pelo mesmo cliente. Você pode usar a função `GuzzleHttp\Promise\each_limit` para executar comandos de envio de diferentes clientes simultaneamente usando um tamanho de grupo fixo.

```
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();
```

### Corrotinas de promessas
<a name="promise-coroutines"></a>

Um dos recursos mais avançados da biblioteca de promessas do Guzzle é que ela permite usar corrotinas de promessas que fazem a criação de fluxos de trabalho assíncronos parecer serem mais como a criação de fluxos de trabalho síncronos tradicionais. Na verdade, o AWS SDK para PHP usa promessas de corrotina na maioria das abstrações de alto nível.

Imagine que você quisesse criar vários buckets e fazer upload de um arquivo em um bucket quando o bucket se tornasse disponível, e quisesse fazer isso tudo simultaneamente para que ocorresse o mais rápido possível. Você pode fazer isso facilmente combinando várias promessas de corrotina em conjunto usando a função de promessa `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 = ['amzn-s3-demo-bucket1', 'amzn-s3-demo-bucket2', 'amzn-s3-demo-bucket3'];
$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();
```