

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 适用于 PHP 的 AWS SDK 版本 3 中的 Waiter
<a name="guide_waiters"></a>

Waiter 通过对资源进行轮询，以一种抽象方式等待资源进入特定状态，从而更加轻松地使用*最终一致性*系统。您可以查看单一服务客户端版本的 [API 文档](https://docs.aws.amazon.com/aws-sdk-php/v3/api/index.html)，找到客户端支持的 Waiter 列表。要导航到那里，请转到 API 文档中的客户端页面，导航到特定版本号（用日期表示），然后向下滚动到“Waiter”部分。[此链接将带您进入 S3 的“Waiter”部分。](https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#waiters)

在以下示例中，使用 Amazon S3 客户端来创建存储桶。然后使用 Waiter 等待存储桶建好。

```
// Create a bucket
$s3Client->createBucket(['Bucket' => 'amzn-s3-demo-bucket']);

// Wait until the created bucket is available
$s3Client->waitUntil('BucketExists', ['Bucket' => 'amzn-s3-demo-bucket']);
```

如果 Waiter 轮询存储桶次数过多，会引发 `\RuntimeException` 异常。

## Waiter 配置
<a name="waiter-configuration"></a>

Waiter 是由配置选项的关联数组推动的。特定 Waiter 所用的所有选项均有默认值，但可以覆盖这些默认值，以支持不同的等待策略。

将 `@waiter` 选项的关联数组传递到客户端的 `$args` 和 `waitUntil()` 方法的 `getWaiter()` 参数，可以修改 Waiter 配置选项。

```
// Providing custom waiter configuration options to a waiter
$s3Client->waitUntil('BucketExists', [
    'Bucket'  => 'amzn-s3-demo-bucket',
    '@waiter' => [
        'delay'       => 3,
        'maxAttempts' => 10
    ]
]);
```

**delay (int)**  
两次轮询尝试之间的延迟秒数。每个 Waiter 都有默认的 `delay` 配置值，但您可能需要针对具体的使用情形修改此设置。

**maxAttempts (int)**  
Waiter 失败之前轮询尝试的次数上限。此选项可确保您不会无限期地等待某个资源。每个 Waiter 都有默认的 `maxAttempts` 配置值，但您可能需要针对具体的使用情形修改此设置。

**initDelay (int)**  
首次轮询尝试之前等待的秒数。如果您知道某一资源需要一段时间才能进入所需状态，此选项将会很有用。

**before（可调用）**  
一个 PHP 可调用函数，在每次尝试之前调用。该可调用函数根据将要执行的 `Aws\CommandInterface` 命令以及目前已执行的尝试次数调用。`before` 可调用函数的用途可以是在执行命令之前修改命令，或提供进度信息。  

```
use Aws\CommandInterface;

$s3Client->waitUntil('BucketExists', [
    'Bucket'  => 'amzn-s3-demo-bucket',
    '@waiter' => [
        'before' => function (CommandInterface $command, $attempts) {
            printf(
                "About to send %s. Attempt %d\n",
                $command->getName(),
                $attempts
            );
        }
    ]
]);
```

## 异步等待
<a name="async-waiters"></a>

除了同步等待，您还可以调用 Waiter 异步等待，同时发送其他请求或同时等待多个资源。

您可以使用客户端的 `getWaiter($name, array $args = [])` 方法检索客户端的 Waiter，从而访问 Waiter 的 Promise。使用 Waiter 的 `promise()` 方法启动 Waiter。Waiter 中最近执行的 `Aws\CommandInterface` 可满足 Waiter Promise，错误引起的 `RuntimeException` 可拒绝 Waiter Promise。

```
use Aws\CommandInterface;

$waiterName = 'BucketExists';
$waiterOptions = ['Bucket' => 'amzn-s3-demo-bucket'];

// Create a waiter promise
$waiter = $s3Client->getWaiter($waiterName, $waiterOptions);

// Initiate the waiter and retrieve a promise
$promise = $waiter->promise();

// Call methods when the promise is resolved.
$promise
    ->then(function () {
        echo "Waiter completed\n";
    })
    ->otherwise(function (\Exception $e) {
        echo "Waiter failed: " . $e . "\n";
    });

// Block until the waiter completes or fails. Note that this might throw
// a \RuntimeException if the waiter fails.
$promise->wait();
```

公开基于 Promise 的 Waiter API 适用于一些功能强大、开销相对较低的使用情形。例如，如果您希望等待多个资源，并在第一个 Waiter 成功完成后执行某些操作，这时该怎么办呢？

```
use Aws\CommandInterface;

// Create an array of waiter promises
$promises = [
    $s3Client->getWaiter('BucketExists', ['Bucket' => 'a'])->promise(),
    $s3Client->getWaiter('BucketExists', ['Bucket' => 'b'])->promise(),
    $s3Client->getWaiter('BucketExists', ['Bucket' => 'c'])->promise()
];

// Initiate a race between the waiters, fulfilling the promise with the
// first waiter to complete (or the first bucket to become available)
$any = Promise\any($promises)
    ->then(function (CommandInterface $command) {
        // This is invoked with the command that succeeded in polling the
        // resource. Here we can know which bucket won the race.
        echo "The {$command['Bucket']} waiter completed first!\n";
    });

// Force the promise to complete
$any->wait();
```