

AWS SDK for JavaScript v2 はサポート終了となりました。[AWS SDK for JavaScript v3](https://docs.aws.amazon.com//sdk-for-javascript/v3/developer-guide/) に移行することをお勧めします。その他の詳細、移行方法については、こちらの[発表内容](https://aws.amazon.com/blogs//developer/announcing-end-of-support-for-aws-sdk-for-javascript-v2/)を参照してください。

# 非同期的なサービスの呼び出し
<a name="calling-services-asynchronously"></a>

SDK を介して行われるリクエストはすべて非同期です。ブラウザスクリプトを作成するときに、この点に注意してください。通常、ウェブブラウザで実行されている JavaScript には、1 つの実行スレッドしかありません。AWS サービスへの非同期呼び出しを行った後、ブラウザスクリプトは実行を継続し、その過程で、非同期の結果が戻る前に、その結果に依存するコードの実行を試みる可能性があります。

AWS サービスへの非同期呼び出しにはそれらの呼び出しの管理が含まれているため、データが利用可能になる前にコードがデータの使用を試みることはありません。このセクションのトピックでは、非同期呼び出し管理の必要性を説明し、それらを管理するために使用できるさまざまな手法について詳しく説明します。

**Topics**
+ [非同期呼び出しの管理](making-asynchronous-calls.md)
+ [無名コールバック関数の使用](using-a-callback-function.md)
+ [リクエストオブジェクトのイベントリスナーの使用](using-a-response-event-handler.md)
+ [async/await の使用](using-async-await.md)
+ [JavaScript Promises の使用](using-promises.md)

# 非同期呼び出しの管理
<a name="making-asynchronous-calls"></a>

たとえば、e コマースウェブサイトのホームページは、リピート顧客がサインインするようにします。サインインする顧客にとっての利点の 1 つは、サインイン後に、顧客の特定の好みに合わせてサイトがカスタマイズされることです。これを実現するには、以下のことが必要です。

1. 顧客はログインし、サインイン認証情報で認証を受ける必要があります。

1. 顧客の好みは顧客データベースからリクエストされます。

1. データベースは、ページがロードされる前に、サイトのカスタマイズに使用される顧客の好みを提供します。

これらのタスクが同期的に実行される場合、それぞれの処理が完了してからでなければ、次が開始できません。データベースから顧客の好みが返されるまで、ウェブページはロードを終了することができません。しかし、データベースクエリがサーバーに送信された後、ネットワークのボトルネック、異常に高いデータベーストラフィック、またはモバイルデバイスの接続不良のために、顧客データの受信が遅れたり、失敗することさえあります。

このような状況でウェブサイトがフリーズしないようにするため、データベースを非同期的に呼び出します。データベース呼び出しが実行され、非同期リクエストが送信された後も、コードは想定どおりに継続して実行されます。非同期呼び出しのレスポンスを適切に管理しないと、コードは、データベースから返されると想定される情報がまだ利用できないときに、そのデータを使用しようとする可能性があります。

![\[同期実行と非同期実行の違いを表示。\]](http://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/images/async-vs-sync.png)


# 無名コールバック関数の使用
<a name="using-a-callback-function"></a>

`AWS.Request` オブジェクトを作成する各サービスオブジェクトメソッドは、最後のパラメータとして無名コールバック関数を使用できます。このコールバック関数の署名は次のとおりです。

```
function(error, data) {
    // callback handling code
}
```

このコールバック関数が実行されるのは、成功したレスポンスまたはエラーデータが返されたときです。メソッドの呼び出しに成功すると、レスポンスの内容は `data` パラメータでコールバック関数に利用可能になります。呼び出しが成功しない場合、エラーの詳細は `error` パラメータに記載されます。

通常、コールバック関数内のコードはエラーをテストし、エラーが返された場合はそれを処理します。エラーが返されない場合、コードは `data` パラメータからレスポンス内のデータを取得します。コールバック関数の基本的な形式は次の例のようになります。

```
function(error, data) {
    if (error) {
        // error handling code
        console.log(error);
    } else {
        // data handling code
        console.log(data);
    }
}
```

前の例では、エラーまたは返されたデータの詳細がコンソールのログに記録されます。サービスオブジェクトのメソッド呼び出しの一部として渡されるコールバック関数の例を、次に示します。

```
new AWS.EC2({apiVersion: '2014-10-01'}).describeInstances(function(error, data) {
  if (error) {
    console.log(error); // an error occurred
  } else {
    console.log(data); // request succeeded
  }
});
```

## リクエストオブジェクトとレスポンスオブジェクトへのアクセス
<a name="access-request-response"></a>

コールバック関数内で、JavaScript キーワード `this` は、ほとんどのサービスの基盤となる `AWS.Response` オブジェクトを参照します。次の例では、未加工のレスポンスデータとヘッダーをログに記録してデバッグを支援するため、`httpResponse` オブジェクトの `AWS.Response` プロパティをコールバック関数内で使用します。

```
new AWS.EC2({apiVersion: '2014-10-01'}).describeInstances(function(error, data) {
  if (error) {
    console.log(error); // an error occurred
    // Using this keyword to access AWS.Response object and properties
    console.log("Response data and headers: " + JSON.stringify(this.httpResponse));
  } else {
    console.log(data); // request succeeded
  }
});
```

また、`AWS.Response` オブジェクトには元のメソッド呼び出しによって送信された `Request` を含む `AWS.Request` プロパティがあるため、行われたリクエストの詳細にアクセスすることもできます。

# リクエストオブジェクトのイベントリスナーの使用
<a name="using-a-response-event-handler"></a>

サービスオブジェクトメソッドを呼び出すときに、無名コールバック関数を作成してパラメータとして渡さない場合、メソッド呼び出しは `AWS.Request` オブジェクトを生成します。このオブジェクトは `send` メソッドを使用して手動で送信する必要があります。

レスポンスを処理するには、`AWS.Request` オブジェクトのイベントリスナーを作成して、メソッド呼び出しのコールバック関数を登録する必要があります。次の例は、サービスオブジェクトメソッドを呼び出すための `AWS.Request` オブジェクトと、正常に返された場合のイベントリスナーを作成する方法を示しています。

```
// create the AWS.Request object
var request = new AWS.EC2({apiVersion: '2014-10-01'}).describeInstances();

// register a callback event handler
request.on('success', function(response) {
  // log the successful data response
  console.log(response.data); 
});

// send the request
request.send();
```

`send` オブジェクトの `AWS.Request` メソッドが呼び出された後、サービスオブジェクトが `AWS.Response` オブジェクトを受け取った時にイベントハンドラが実行されます。

`AWS.Request` オブジェクトの詳細については、 API リファレンスの「[https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html) 」を参照してください。`AWS.Response` オブジェクトの詳細については、 API リファレンスの「[レスポンスオブジェクトの使用](the-response-object.md) 」または「[https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Response.html](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Response.html)」を参照してください。

## 複数のコールバックの連結
<a name="response-chaining-callbacks"></a>

任意のリクエストオブジェクトで複数のコールバックを登録できます。複数のコールバックを異なるイベントに登録するか、または同じイベントに対して登録できます。また、次の例のようにコールバックを連結させることもできます。

```
request.
  on('success', function(response) {
    console.log("Success!");
  }).
  on('error', function(response) {
    console.log("Error!");
  }).
  on('complete', function() {
    console.log("Always!");
  }).
  send();
```

## リクエストオブジェクトの完了イベント
<a name="request-object-completion-events"></a>

`AWS.Request` オブジェクトは、各サービスオペレーションメソッドのレスポンスに基づいてこれらの完了イベントを発生させます。
+ `success`
+ `error`
+ `complete`

これらのイベントのいずれかに対応するコールバック関数を登録できます。すべてのリクエストオブジェクトイベントの完全なリストについては、API リファレンスの「[https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html)」を参照してください。

### 成功イベント
<a name="request-success-event"></a>

`success` イベントは、サービスオブジェクトから受け取った正常なレスポンスに応じて発生します。次に、このイベントのコールバック関数を登録する方法を示します。

```
request.on('success', function(response) { 
  // event handler code
});
```

レスポンスは、サービスからのシリアル化されたレスポンスデータを含む `data` プロパティを提供します。例えば、Amazon S3 サービスオブジェクトの `listBuckets` メソッドに対する以下の呼び出し

```
s3.listBuckets.on('success', function(response) {
  console.log(response.data);
}).send();
```

レスポンスを返してから、以下の `data` プロパティの内容をコンソールに出力します。

```
{ Owner: { ID: '...', DisplayName: '...' },
  Buckets: 
   [ { Name: 'someBucketName', CreationDate: someCreationDate },
     { Name: 'otherBucketName', CreationDate: otherCreationDate } ],
  RequestId: '...' }
```

### エラーイベント
<a name="request-error-event"></a>

`error` イベントは、サービスオブジェクトから受け取ったエラーレスポンスに応じて発生します。次に、このイベントのコールバック関数を登録する方法を示します。

```
request.on('error', function(error, response) { 
  // event handling code
});
```

`error` イベントが発生すると、レスポンスの `data` プロパティの値は `null` になり、`error` プロパティにはエラーデータが含まれます。関連付けられた `error` オブジェクトは、登録済みコールバック関数への最初のパラメータとして渡されます。たとえば、以下のコードは、

```
s3.config.credentials.accessKeyId = 'invalid';
s3.listBuckets().on('error', function(error, response) {
  console.log(error);
}).send();
```

エラーを返してから、以下のエラーデータをコンソールに出力します。

```
{ code: 'Forbidden', message: null }
```

### 完了イベント
<a name="request-complete-event"></a>

呼び出しが成功したか、エラーになったかにかかわらず、`complete` イベントはサービスオブジェクト呼び出しが終了したときに発生します。次に、このイベントのコールバック関数を登録する方法を示します。

```
request.on('complete', function(response) { 
  // event handler code
});
```

成功またはエラーに関係なく実行する必要があるすべてのリクエストのクリーンアップを処理するには、`complete` イベントコールバックを使用します。`complete` イベントのコールバック内でレスポンスデータを使用する場合は、次の例に示すように、どちらかにアクセスする前にまず `response.data` か `response.error` のプロパティを確認してください。

```
request.on('complete', function(response) {
  if (response.error) {
    // an error occurred, handle it
  } else {
    // we can use response.data here
  }
}).send();
```

## リクエストオブジェクトの HTTP イベント
<a name="request-object-http-events"></a>

`AWS.Request` オブジェクトは、各サービスオペレーションメソッドのレスポンスに基づいてこれらの HTTP イベントを発生させます。
+ `httpHeaders`
+ `httpData`
+ `httpUploadProgress`
+ `httpDownloadProgress`
+ `httpError`
+ `httpDone`

これらのイベントのいずれかに対応するコールバック関数を登録できます。すべてのリクエストオブジェクトイベントの完全なリストについては、API リファレンスの「[https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html)」を参照してください。

### httpHeaders イベント
<a name="request-httpheaders-event"></a>

`httpHeaders` イベントは、ヘッダーがリモートサーバーによって送信されたときに発生します。次に、このイベントのコールバック関数を登録する方法を示します。

```
request.on('httpHeaders', function(statusCode, headers, response) {
  // event handling code
});
```

コールバック関数の `statusCode` パラメータは HTTP ステータスコードです。`headers` パラメータにはレスポンスヘッダーが入ります。

### httpData イベント
<a name="request-httpdata-event"></a>

`httpData` イベントは、サービスからのレスポンスデータパケットをストリーミングするために発生します。次に、このイベントのコールバック関数を登録する方法を示します。

```
request.on('httpData', function(chunk, response) {
  // event handling code
});
```

通常、このイベントは、レスポンス全体をメモリにロードするのが現実的ではない場合に、大量のレスポンスをチャンクに分けて受信するために使用されます。このイベントには、サーバーからの実際のデータの一部を含む、追加の `chunk` パラメータがあります。

`httpData` イベントのコールバックを登録すると、レスポンスの `data` プロパティにはリクエスト用にシリアル化された出力全体が含まれます。組み込みハンドラ用の余分な解析とメモリーのオーバーヘッドがない場合、デフォルトの `httpData` リスナーを削除する必要があります。

### httpDownloadProgress と httpUploadProgress イベント
<a name="request-httpupload-download-progress-event"></a>

`httpUploadProgress` イベントは、HTTP リクエストがさらにデータをアップロードしたときに発生します。同様に、`httpDownloadProgress` イベントは、HTTP リクエストがさらにデータをダウンロードしたときに発生します。次に、これらのイベントのコールバック関数を登録する方法を示します。

```
request.on('httpUploadProgress', function(progress, response) {
  // event handling code
})
.on('httpDownloadProgress', function(progress, response) {
  // event handling code
});
```

コールバック関数の `progress` パラメータには、リクエストのロード済みバイト数と合計バイト数を含むオブジェクトが含まれています。

### httpError イベント
<a name="request-httperror-event"></a>

`httpError` イベントは、HTTP リクエストが失敗した場合に発生します。次に、このイベントのコールバック関数を登録する方法を示します。

```
request.on('httpError', function(error, response) {
  // event handling code
});
```

コールバック関数の `error` パラメータには、スローされたエラーが含まれています。

### httpDone イベント
<a name="request-httpdone-event"></a>

`httpDone` イベントは、サーバーのデータ送信が終了すると発生します。次に、このイベントのコールバック関数を登録する方法を示します。

```
request.on('httpDone', function(response) {
  // event handling code
});
```

# async/await の使用
<a name="using-async-await"></a>

AWS SDK for JavaScript への呼び出しで `async/await` パターンを使用できます。コールバックを受け取るほとんどの関数は、promise を返しません。promise を返す `await` 関数のみを使用するため、`async/await` パターンを使用するには、`.promise()` メソッドを呼び出しの最後にチェーンし、コールバックを削除する必要があります。

次の例では、async/await を使用して、すべての Amazon DynamoDB テーブルを `us-west-2` で一覧表示します。

```
var AWS = require("aws-sdk");
//Create an Amazon DynamoDB client service object.
dbClient = new AWS.DynamoDB({ region: "us-west-2" });
// Call DynamoDB to list existing tables
const run = async () => {
  try {
    const results = await dbClient.listTables({}).promise();
    console.log(results.TableNames.join("\n"));
  } catch (err) {
    console.error(err);
  }
};
run();
```

**注記**  
 すべてのブラウザが async/await をサポートしているわけではありません。非同期/待機をサポートするブラウザのリストについては、[非同期関数](https://caniuse.com/#feat=async-functions)を参照してください。

# JavaScript Promises の使用
<a name="using-promises"></a>

`AWS.Request.promise` メソッドは、コールバックを使用する代わりに、サービスオペレーションを呼び出して非同期フローを管理する方法を提供します。Node.js とブラウザスクリプトでは、コールバック関数なしでサービスオペレーションが呼び出された場合に `AWS.Request` オブジェクトが返されます。リクエストの `send` メソッドを呼び出して、サービスの呼び出しを行うことができます。

ただし、`AWS.Request.promise` はすぐにサービス呼び出しを開始し、レスポンス `data` プロパティで満たされるか、レスポンス `error` プロパティで拒否された promise のいずれかを返します。

```
var request = new AWS.EC2({apiVersion: '2014-10-01'}).describeInstances();

// create the promise object
var promise = request.promise();

// handle promise's fulfilled/rejected states
promise.then(
  function(data) {
    /* process the data */
  },
  function(error) {
    /* handle the error */
  }
);
```

次の例は、`data` オブジェクトで満たされるか、`error` オブジェクトで拒否された promise を返します。promises を使用すると、1 つのコールバックだけでエラーを検出することはありません。代わりに、リクエストの成功または失敗に基づいて、正しいコールバックが呼び出されます。

```
var s3 = new AWS.S3({apiVersion: '2006-03-01', region: 'us-west-2'});
var params = {
  Bucket: 'bucket',
  Key: 'example2.txt',
  Body: 'Uploaded text using the promise-based method!'
};
var putObjectPromise = s3.putObject(params).promise();
putObjectPromise.then(function(data) {
  console.log('Success');
}).catch(function(err) {
  console.log(err);
});
```

## 複数の Promises の調整
<a name="multiple-promises"></a>

状況によって、コードは複数の非同期呼び出しを行う必要があります。すべてが正常に返されたときのみ、これらの呼び出しに対する操作が必要です。これらの個々の非同期メソッド呼び出しを promises で管理する場合、`all` メソッドを使用する追加の promise を作成することができます。このメソッドは、ユーザーがメソッドに渡す promise の配列が満たされた場合に、この包括的な promise を満たします。コールバック関数には、`all` メソッドに渡された promises の値の配列が渡されます。

次の例で、AWS Lambda 関数は Amazon DynamoDB に対して 3 回の非同期呼び出しを行う必要があります。ただし、各呼び出しの promise が満たされた後にのみ完了することができます。

```
Promise.all([firstPromise, secondPromise, thirdPromise]).then(function(values) {
  
  console.log("Value 0 is " + values[0].toString);
  console.log("Value 1 is " + values[1].toString);
  console.log("Value 2 is " + values[2].toString);

  // return the result to the caller of the Lambda function
  callback(null, values);
});
```

## ブラウザおよび Node.js による Promises のサポート
<a name="browser-node-promise-support"></a>

ネイティブ JavaScript の promises (ECMAScript 2015) のサポートは、コードが実行される JavaScript エンジンとバージョンによって異なります。コードを実行する必要がある各環境における JavaScript のサポートを確認するには、GitHub の「[ECMAScript 適合表](https://compat-table.github.io/compat-table/es6/)」を参照してください。

## その他の Promise 実装の使用
<a name="using-other-promise-implementations"></a>

ECMAScript 2015 でのネイティブの promise 実装に加えて、以下を含むサードパーティーの promise ライブラリも使用できます。
+ [bluebird](http://bluebirdjs.com)
+ [RSVP](https://github.com/tildeio/rsvp.js/)
+ [Q](https://github.com/kriskowal/q)

これらオプションの promise ライブラリは、ECMAScript 5 および ECMAScript 2015 のネイティブの promise 実装をサポートしていない環境でコードを実行する必要がある場合に便利です。

サードパーティーの promise ライブラリを使用するには、グローバル設定オブジェクトの `setPromisesDependency` メソッドを呼び出して、SDK に promises の依存関係を設定します。ブラウザスクリプトでは、必ず SDK をロードする前にサードパーティーの promise ライブラリをロードしてください。次の例で、SDK は bluebird の promise ライブラリの実装を使用するように設定されています。

```
AWS.config.setPromisesDependency(require('bluebird'));
```

再び JavaScript エンジンのネイティブの promise 実装を使用するには、再度 `setPromisesDependency` を呼び出して、ライブラリ名の代わりに `null` を渡します。