

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 JavaScript 編寫 Amazon DynamoDB 程式
<a name="programming-with-javascript"></a>

本指南為想要搭配 JavaScript 使用 Amazon DynamoDB 的程式設計人員提供指導。了解 適用於 JavaScript 的 AWS SDK、可用的抽象層、設定連線、處理錯誤、定義重試政策、管理保持連線等。

**Topics**
+ [關於 適用於 JavaScript 的 AWS SDK](#programming-with-javascript-about)
+ [使用 適用於 JavaScript 的 AWS SDK V3](#programming-with-javascript-using-the-sdk)
+ [存取 JavaScript 文件](#programming-with-javascript-documentation)
+ [抽象層](#programming-with-javascript-abstraction-layers)
+ [使用 marshall 公用程式函數](#programming-with-javascript-using-marshall-utility)
+ [讀取項目](#programming-with-javascript-reading-items)
+ [條件式寫入](#programming-with-javascript-conditional-writes)
+ [分頁](#programming-with-javascript-pagination)
+ [指定組態](#programming-with-javascript-config)
+ [等待程式](#programming-with-javascript-waiters)
+ [錯誤處理](#programming-with-javascript-error-handling)
+ [日誌](#programming-with-javascript-logging)
+ [考量事項](#programming-with-javascript-considerations)

## 關於 適用於 JavaScript 的 AWS SDK
<a name="programming-with-javascript-about"></a>

 適用於 JavaScript 的 AWS SDK 可讓您 AWS 服務 使用瀏覽器指令碼或 Node.js 存取 。本文件著重於最新版本的 SDK (V3)。V3 適用於 JavaScript 的 AWS SDK 由 維護 AWS 為 [ GitHub 上託管的開放原始碼專案](https://github.com/aws/aws-sdk-js-v3)。問題和功能請求是公開的，您可以在 GitHub 儲存庫的問題頁面上存取它們。

JavaScript V2 類似於 V3，但包含語法差異。V3 更模組化，可更輕鬆地提供較小的相依性，並具有一級 TypeScript 支援。我們建議您使用最新版的 SDK。

## 使用 適用於 JavaScript 的 AWS SDK V3
<a name="programming-with-javascript-using-the-sdk"></a>

您可以使用 Node Package Manager 將 SDK 新增至 Node.js 應用程式。以下範例示範如何新增最常用於 DynamoDB 的 SDK 套件。
+ `npm install @aws-sdk/client-dynamodb`
+ `npm install @aws-sdk/lib-dynamodb`
+ `npm install @aws-sdk/util-dynamodb`

安裝套件會將參考新增至 package.json 專案檔案的相依性區段。您可以選擇使用較新的 ECMAScript 模組語法。如需這兩種方法的進一步詳細資訊，請參閱考量一節。

## 存取 JavaScript 文件
<a name="programming-with-javascript-documentation"></a>

使用下列資源開始使用 JavaScript 文件：
+ 存取[開發人員指南](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/welcome.html)以取得核心 JavaScript 文件。安裝指示位於**設定**區段。
+ 存取 [API 參考](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/introduction/)文件，以探索所有可用的類別和方法。
+ 適用於 JavaScript 的 SDK 支援 DynamoDB AWS 服務 以外的許多 。使用下列程序來尋找 DynamoDB 的特定 API 涵蓋範圍：

  1. 從**服務**中，選擇 **DynamoDB 和程式庫**。這會記錄低階用戶端。

  1. 選擇 **lib-dynamodb**。這會記錄高階用戶端。兩個用戶端代表您可以選擇使用的兩個不同的抽象層。如需抽象層的詳細資訊，請參閱以下章節。

## 抽象層
<a name="programming-with-javascript-abstraction-layers"></a>

適用於 JavaScript V3 的 SDK 具有低階用戶端 (`DynamoDBClient`) 和高階用戶端 (`DynamoDBDocumentClient`)。

**Topics**
+ [低階客戶端 (`DynamoDBClient`)](#programming-with-javascript-low-level-client)
+ [高階用戶端 (`DynamoDBDocumentClient`)](#programming-with-javascript-high-level-client)

### 低階客戶端 (`DynamoDBClient`)
<a name="programming-with-javascript-low-level-client"></a>

低階用戶端對於基礎線路通訊協定不提供額外的抽象概念。它可讓您完全控制通訊的各個層面，但由於沒有抽象概念，因此您必須使用 DynamoDB JSON 格式執行提供項目定義等操作。

如以下範例所示，使用此格式的資料類型必須明確陳述。*S* 表示字串值，*N* 表示數值。線路上的數字一律會以標記為數字類型的字串傳送，以確保精確度不會遺失。低階 API 呼叫的命名模式例如 `PutItemCommand` 和 `GetItemCommand`。

下列範例使用低階用戶端，搭配利用 DynamoDB JSON 定義的 `Item`：

```
const { DynamoDBClient, PutItemCommand } = require("@aws-sdk/client-dynamodb");

const client = new DynamoDBClient({});

async function addProduct() {
  const params = {
    TableName: "products",
    Item: {
      "id": { S: "Product01" },
      "description": { S: "Hiking Boots" },
      "category": { S: "footwear" },
      "sku": { S: "hiking-sku-01" },
      "size": { N: "9" }
    }
  };

  try {
    const data = await client.send(new PutItemCommand(params));
    console.log('result : ' + JSON.stringify(data));
  } catch (error) {
    console.error("Error:", error);
  }
}
addProduct();
```

### 高階用戶端 (`DynamoDBDocumentClient`)
<a name="programming-with-javascript-high-level-client"></a>

高階 DynamoDB 文件用戶端提供內建的便利功能，例如不需要手動封送資料，以及允許使用標準 JavaScript 物件直接讀取和寫入。[`lib-dynamodb` 文件](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-lib-dynamodb/)提供優點清單。

若要執行個體化 `DynamoDBDocumentClient`，請建構低階 `DynamoDBClient`，然後使用 `DynamoDBDocumentClient` 包裝它。函數命名慣例在兩個套件之間略有不同。例如，低階使用 `PutItemCommand`，而高階使用 `PutCommand`。不同的名稱允許兩組函數在相同的內容中共存，讓您可以在相同的指令碼中混合兩者。

```
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
const { DynamoDBDocumentClient, PutCommand } = require("@aws-sdk/lib-dynamodb");

const client = new DynamoDBClient({});

const docClient = DynamoDBDocumentClient.from(client);

async function addProduct() {
  const params = {
    TableName: "products",
    Item: {
      id: "Product01",
      description: "Hiking Boots",
      category: "footwear",
      sku: "hiking-sku-01",
      size: 9,
    },
  };

  try {
    const data = await docClient.send(new PutCommand(params));
    console.log('result : ' + JSON.stringify(data));
  } catch (error) {
    console.error("Error:", error);
  }
}

addProduct();
```

當您使用 `GetItem`、`Query` 或 `Scan` 等 API 操作讀取項目時，使用模式是一致的。

## 使用 marshall 公用程式函數
<a name="programming-with-javascript-using-marshall-utility"></a>

您可以自行使用低階用戶端和封送或取消封送資料類型。公用程式套件 [util-dynamodb](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-util-dynamodb/) 具有 `marshall()` 公用程式函數，可接受 JSON 並產生 DynamoDB JSON，以及反向執行的 `unmarshall()` 函數。下列範例使用低階用戶端搭配由 `marshall()` 呼叫處理的資料封送。

```
const { DynamoDBClient, PutItemCommand } = require("@aws-sdk/client-dynamodb");
const { marshall } = require("@aws-sdk/util-dynamodb");

const client = new DynamoDBClient({});

async function addProduct() {
  const params = {
    TableName: "products",
    Item: marshall({
      id: "Product01",
      description: "Hiking Boots",
      category: "footwear",
      sku: "hiking-sku-01",
      size: 9,
    }),
  };

  try {
    const data = await client.send(new PutItemCommand(params));
  } catch (error) {
    console.error("Error:", error);
  }
}
addProduct();
```

## 讀取項目
<a name="programming-with-javascript-reading-items"></a>

若要從 DynamoDB 資料表讀取項目，請使用 `GetItem` API 操作。與 `PutItem` 命令類似，您可以選擇使用低階用戶端或高階文件用戶端。以下範例示範如何使用高階文件用戶端擷取項目。

```
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
const { DynamoDBDocumentClient, GetCommand } = require("@aws-sdk/lib-dynamodb");

const client = new DynamoDBClient({});

const docClient = DynamoDBDocumentClient.from(client);

async function getProduct() {
  const params = {
    TableName: "products",
    Key: {
      id: "Product01",
    },
  };

  try {
    const data = await docClient.send(new GetCommand(params));
    console.log('result : ' + JSON.stringify(data));
  } catch (error) {
    console.error("Error:", error);
  }
}

getProduct();
```

使用 `Query` API 操作讀取多個項目。您可以使用低階用戶端或文件用戶端。以下範例使用高階文件用戶端。

```
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
const {
  DynamoDBDocumentClient,
  QueryCommand,
} = require("@aws-sdk/lib-dynamodb");

const client = new DynamoDBClient({});

const docClient = DynamoDBDocumentClient.from(client);

async function productSearch() {
  const params = {
    TableName: "products",
    IndexName: "GSI1",
    KeyConditionExpression: "#category = :category and begins_with(#sku, :sku)",
    ExpressionAttributeNames: {
      "#category": "category",
      "#sku": "sku",
    },
    ExpressionAttributeValues: {
      ":category": "footwear",
      ":sku": "hiking",
    },
  };

  try {
    const data = await docClient.send(new QueryCommand(params));
    console.log('result : ' + JSON.stringify(data));
  } catch (error) {
    console.error("Error:", error);
  }
}

productSearch();
```

## 條件式寫入
<a name="programming-with-javascript-conditional-writes"></a>

DynamoDB 寫入操作可以指定邏輯條件表達式，必須評估為 true 才能繼續寫入。如果條件未評估為 true，寫入操作會產生例外狀況。條件表達式可以檢查項目是否已存在，或其屬性是否符合特定限制條件。

`ConditionExpression = "version = :ver AND size(VideoClip) < :maxsize" `

當條件式表達式失敗時，您可以使用 `ReturnValuesOnConditionCheckFailure` 來請求錯誤回應包含不符合條件的項目，以推斷問題所在。如需詳細資訊，請參閱[使用 Amazon DynamoDB 在高並行情況下處理條件式寫入錯誤](https://aws.amazon.com/blogs/database/handle-conditional-write-errors-in-high-concurrency-scenarios-with-amazon-dynamodb/)。

```
try {
      const response = await client.send(new PutCommand({
          TableName: "YourTableName",
          Item: item,
          ConditionExpression: "attribute_not_exists(pk)",
          ReturnValuesOnConditionCheckFailure: "ALL_OLD"
      }));
  } catch (e) {
      if (e.name === 'ConditionalCheckFailedException') {
          console.log('Item already exists:', e.Item);
      } else {
          throw e;
      }
  }
```

其他程式碼範例顯示 JavsScript SDK V3 用量的其他層面，可在 [JavaScript SDK V3 文件](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/javascript_dynamodb_code_examples.html)和 [DynamoDB-SDK-Examples GitHub 儲存庫](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/examples/SDK/node.js)下取得。

## 分頁
<a name="programming-with-javascript-pagination"></a>

**Topics**
+ [使用 `paginateScan` 便利方法](#using-the-paginatescan-convenience-method)

`Scan` 或 `Query` 等讀取請求可能會傳回資料集中的多個項目。如果您使用 `Limit` 參數執行 `Scan` 或 `Query`，一旦系統讀取到該項目數時，就會傳送部分回應，而且您需要分頁才能擷取其他項目。

對於每個請求，系統最多只會讀取 1 MB 的資料。如果您包含 `Filter` 表達式，系統仍將從磁碟讀取最多 1 MB 的資料，但會傳回該 MB 中符合篩選條件的項目。篩選操作可能從頁面傳回 0 個項目，但在搜尋窮盡之前仍需要進一步分頁。

您應該在回應中尋找 `LastEvaluatedKey`，並在後續請求中使用它做為 `ExclusiveStartKey` 參數，以繼續資料擷取。這可做為書籤，如下列範例所述。

**注意**  
在第一次迭代時，該範例會傳遞 null `lastEvaluatedKey` 做為 `ExclusiveStartKey`，這是允許的。

使用 `LastEvaluatedKey` 的範例：

```
const { DynamoDBClient, ScanCommand } = require("@aws-sdk/client-dynamodb");

const client = new DynamoDBClient({});

async function paginatedScan() {
  let lastEvaluatedKey;
  let pageCount = 0;

  do {
    const params = {
      TableName: "products",
      ExclusiveStartKey: lastEvaluatedKey,
    };

    const response = await client.send(new ScanCommand(params));
    pageCount++;
    console.log(`Page ${pageCount}, Items:`, response.Items);
    lastEvaluatedKey = response.LastEvaluatedKey;
  } while (lastEvaluatedKey);
}

paginatedScan().catch((err) => {
  console.error(err);
});
```

### 使用 `paginateScan` 便利方法
<a name="using-the-paginatescan-convenience-method"></a>



開發套件提供稱為 `paginateScan` 和 `paginateQuery` 的便利方法，可在幕後為您執行此操作並重複提出請求。使用標準 `Limit` 參數指定每個請求要讀取的項目數量上限。

```
const { DynamoDBClient, paginateScan } = require("@aws-sdk/client-dynamodb");

const client = new DynamoDBClient({});

async function paginatedScanUsingPaginator() {
  const params = {
    TableName: "products",
    Limit: 100
  };

  const paginator = paginateScan({client}, params);

  let pageCount = 0;

  for await (const page of paginator) {
    pageCount++;
    console.log(`Page ${pageCount}, Items:`, page.Items);
  }
}

paginatedScanUsingPaginator().catch((err) => {
  console.error(err);
});
```

**注意**  
除非資料表很小，否則不建議採用定期執行完整資料表掃描的存取模式。

## 指定組態
<a name="programming-with-javascript-config"></a>

**Topics**
+ [逾時的組態](#programming-with-javascript-config-timeouts)
+ [保持連線的組態](#programming-with-javascript-config-keep-alive)
+ [重試的組態](#programming-with-javascript-config-retries)

設定 `DynamoDBClient` 時，您可以將組態物件傳遞至建構函數，以指定各種組態覆寫。例如，如果呼叫內容還不知道，您可以指定要連線的區域，或指定要使用的端點 URL。如果您想要針對 DynamoDB 本機版執行個體進行開發，這非常有用。

```
const client = new DynamoDBClient({
  region: "eu-west-1",
  endpoint: "http://localhost:8000",
});
```

### 逾時的組態
<a name="programming-with-javascript-config-timeouts"></a>

DynamoDB 使用 HTTPS 進行用戶端-伺服器通訊。您可以透過提供 `NodeHttpHandler` 物件來控制 HTTP 層的某些層面。例如，您可以調整金鑰逾時值 `connectionTimeout` 和 `requestTimeout`。`connectionTimeout` 是用戶端在嘗試建立連線後放棄連線時所等待的最長持續時間，以毫秒為單位。

`requestTimeout` 定義傳送請求後用戶端等待回應的時間長度，也以毫秒為單位。兩者的預設值都是零，表示逾時已停用，而且如果未收到回應，用戶端等待的時間將沒有極限。您應該將逾時設定為合理值，以便在發生網路問題時，請求會因逾時而發出錯誤，並可啟動新的請求。例如：

```
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { NodeHttpHandler } from "@smithy/node-http-handler";

const requestHandler = new NodeHttpHandler({
  connectionTimeout: 2000,
  requestTimeout: 2000,
});

const client = new DynamoDBClient({
  requestHandler
});
```

**注意**  
提供的範例使用 [Smithy](https://smithy.io/2.0/index.html) 匯入。Smithy 是一種用於定義服務和 SDK 的語言，屬於開放原始碼，並由 AWS維護。

除了設定逾時值之外，您還可以設定通訊端數量上限，以增加每個原始伺服器的並行連線數量。開發人員指南包含[設定 `maxSockets` 參數的詳細資訊](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-configuring-maxsockets.html)。

### 保持連線的組態
<a name="programming-with-javascript-config-keep-alive"></a>

使用 HTTPS 時，第一個請求一律需要一些來回通訊才能建立安全連線。HTTP Keep-Alive 允許後續請求重複使用已建立的連線，使請求更有效率並降低延遲。JavaScript V3 預設會啟用 HTTP Keep-Alive。

閒置連線可以保持運作的時間有限制。如果您有閒置連線，但希望下一個請求使用已建立的連線，請考慮每分鐘傳送定期請求。

**注意**  
請注意，在較舊的 SDK V2 中，保持連線預設為關閉，這表示每個連線都會在使用後立即關閉。如果使用 V2，您可以覆寫此設定。

### 重試的組態
<a name="programming-with-javascript-config-retries"></a>

當 SDK 收到錯誤回應，且 SDK 判斷該錯誤是可恢復的，例如限流例外狀況或暫時服務例外狀況時，將會再次重試。身為呼叫者的您不會察覺到這一切，但您可能會注意到請求需要更長的時間才能成功。

根據預設，適用於 JavaScript V3 的 SDK 會在放棄錯誤並將其傳遞至呼叫內容之前，發出總共 3 次請求。您可以調整這些重試次數和頻率。

`DynamoDBClient` 建構函數接受會限制將要嘗試多少次的 `maxAttempts` 設定。以下範例會將該值從預設值 3 提高為總計 5 次。如果您將其設定為 0 或 1，表示您不希望任何自動重試，並想要自行在擷取區塊內處理任何可恢復的錯誤。

```
const client = new DynamoDBClient({
  maxAttempts: 5,
});
```

您也可以使用自訂重試策略來控制重試的時間。若要這樣做，請匯入 `util-retry` 公用程式套件，並建立自訂退避函數，根據目前的重試計數計算重試之間的等待時間。

以下範例顯示，如果第一次嘗試失敗，最多嘗試 5 次，延遲為 15、30、90 和 360 毫秒。自訂退避函數 ` calculateRetryBackoff` 會接受重試嘗試次數 (從第一次重試的 1 開始) 來計算延遲，並傳回該請求應等待的毫秒數。

```
const { ConfiguredRetryStrategy } = require("@aws-sdk/util-retry");

const calculateRetryBackoff = (attempt) => {
  const backoffTimes = [15, 30, 90, 360];
  return backoffTimes[attempt - 1] || 0;
};

const client = new DynamoDBClient({
  retryStrategy: new ConfiguredRetryStrategy(
    5, // max attempts.
    calculateRetryBackoff // backoff function.
  ),
});
```

## 等待程式
<a name="programming-with-javascript-waiters"></a>

DynamoDB 用戶端包含兩個有用的[等待程式函數](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/dynamodb/wait/index.html#cli-aws-dynamodb-wait)，當您希望程式碼等待資料表修改完成後才繼續執行時，可在建立、修改或刪除資料表時使用。例如，您可以部署資料表、呼叫 `waitUntilTableExists` 函數，而且程式碼會封鎖，直到資料表變成 **ACTIVE** 為止。等待程式每 20 秒會以 `describe-table` 輪詢一次 DynamoDB 服務。

```
import {waitUntilTableExists, waitUntilTableNotExists} from "@aws-sdk/client-dynamodb";

… <create table details>

const results = await waitUntilTableExists({client: client, maxWaitTime: 180}, {TableName: "products"});
if (results.state == 'SUCCESS') {
  return results.reason.Table
}
console.error(`${results.state} ${results.reason}`);
```

`waitUntilTableExists` 功能只會在可以執行會顯示資料表狀態 **ACTIVE** 的 `describe-table` 命令時傳回控制項。這可確保您可以使用 `waitUntilTableExists` 等待建立完成，以及新增 GSI 索引等修改，這可能需要一些時間來套用，資料表才會返回 **ACTIVE** 狀態。

## 錯誤處理
<a name="programming-with-javascript-error-handling"></a>

在這裡的早期範例中，我們概括地發現了所有錯誤。不過，在實際的應用程式中，區分各種錯誤類型並實作更精確的錯誤處理非常重要。

DynamoDB 錯誤回應包含中繼資料，包括錯誤的名稱。您可以擷取錯誤，然後比對可能的錯誤情況字串名稱，以判斷如何繼續。對於伺服器端錯誤，您可以利用 `instanceof` 運算子搭配 `@aws-sdk/client-dynamodb` 套件匯出的錯誤類型，有效率地管理錯誤處理。

請務必注意，這些錯誤只有在所有重試都用盡之後才會顯示。如果重試錯誤，且最終接續成功呼叫，從程式碼的角度來看並沒有錯誤，只是延遲稍微增加了。重試會在 Amazon CloudWatch 圖表中顯示為失敗的請求，例如限流或錯誤請求。如果用戶端達到重試計數上限，則會放棄並產生例外狀況。這是用戶端表達其不會重試的方式。

以下是擷取錯誤並根據傳回的錯誤類型採取行動的程式碼片段。

```
import {
  ResourceNotFoundException
  ProvisionedThroughputExceededException,
  DynamoDBServiceException,
} from "@aws-sdk/client-dynamodb";

try {
  await client.send(someCommand);
} catch (e) {
    if (e instanceof ResourceNotFoundException) {
      // Handle ResourceNotFoundException
    } else if (e instanceof ProvisionedThroughputExceededException) {
      // Handle ProvisionedThroughputExceededException
    } else if (e instanceof DynamoDBServiceException) {
      // Handle DynamoDBServiceException
    } else {
      // Other errors such as those from the SDK
      if (e.name === "TimeoutError") {
        // Handle SDK TimeoutError.
      } else {
        // Handle other errors.
      }
    }
}
```

請參閱《DynamoDB 開發人員指南》**中的常見 [使用 DynamoDB 時發生錯誤](Programming.Errors.md) 錯誤字串。您可以在該 API 呼叫的文件中找到任何特定 API 呼叫的確切錯誤，例如[查詢 API 文件](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html)。

錯誤中繼資料包含其他屬性，視錯誤而定。對於 ` TimeoutError`，中繼資料包含已嘗試的次數和 `totalRetryDelay`，如下所示。

```
{
  "name": "TimeoutError",
  "$metadata": {
    "attempts": 3,
    "totalRetryDelay": 199
  }
}
```

如果您管理自己的重試政策，您會想要區分限流和錯誤：
+ **限流** (由 ` ProvisionedThroughputExceededException` 或 `ThrottlingException` 表示) 表示運作狀態良好的服務，通知您已超過 DynamoDB 資料表或分割區的讀取或寫入容量。每經過一毫秒，就能獲得更多讀取或寫入容量，因此您可以快速重試，例如每 50 毫秒，以嘗試存取該新發布的容量。

   使用限流時，您不需要特別使用指數退避，因為傳回限流對 DynamoDB 很輕量，而且不會向您收取每次請求的費用。指數退避會將較長的延遲指派給已等待最長時間的用戶端執行緒，以統計方式將 p50 和 p99 向外延伸。
+ **錯誤** (由 ` InternalServerError` 或 `ServiceUnavailable` 等表示) 表示服務的暫時性問題，可能是整個資料表，也可能是您正在讀取或寫入的分割區。發生錯誤時，您可以在重試之前暫停更長的時間，例如 250 毫秒或 500 毫秒，並使用抖動來交錯重試。

## 日誌
<a name="programming-with-javascript-logging"></a>

開啟記錄功能，以取得 SDK 正在執行之作業的詳細資訊。您可以在 `DynamoDBClient` 上設定參數，如以下範例所示。更多日誌資訊會顯示在主控台中，並包含中繼資料，例如狀態碼和耗用容量。如果您於本機上在終端機視窗中執行程式碼，日誌會顯示在該處。如果您在 中執行程式碼 AWS Lambda，且已設定 Amazon CloudWatch logs，則會在該處寫入主控台輸出。

```
const client = new DynamoDBClient({
  logger: console
});
```

您也可以連接到內部 SDK 活動，並在發生特定事件時執行自訂記錄。以下範例使用用戶端的 `middlewareStack` 攔截從 SDK 傳送的每個請求，並在發生時記錄該請求。

```
const client = new DynamoDBClient({});

client.middlewareStack.add(
  (next) => async (args) => {
    console.log("Sending request from AWS SDK", { request: args.request });
    return next(args);
  },
  {
    step: "build",
    name: "log-ddb-calls",
  }
);
```

`MiddlewareStack` 提供強大的勾點，用於觀察和控制 SDK 行為。如需詳細資訊，請參閱 部落格[簡介模組化 Middleware Stack 適用於 JavaScript 的 AWS SDK](https://aws.amazon.com/blogs/developer/middleware-stack-modular-aws-sdk-js/)。

## 考量事項
<a name="programming-with-javascript-considerations"></a>

在專案 適用於 JavaScript 的 AWS SDK 中實作 時，以下是一些需要考慮的進一步因素。

**模組系統**  
開發套件支援兩個模組系統：CommonJS 和 ES (ECMAScript)。CommonJS 使用 `require` 函數，而 ES 則使用 `import` 關鍵字。  

1. **CommonJS** – `const { DynamoDBClient, PutItemCommand } = require("@aws-sdk/client-dynamodb");`

1. **ES (ECMAScript** – `import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb";`
專案類型指定要使用的模組系統，並在 package.json 檔案的類型區段中指定。預設為 CommonJS。使用 `"type": "module"` 來指示 ES 專案。如果您有使用 CommonJS 套件格式的現有 Node.JS 專案，您仍然可以使用 .mjs 副檔名來命名函數檔案，以新增具有更現代化 SDK V3 匯入語法的函數。這將允許把程式碼檔案視為 ES (ECMAScript)。

**非同步操作**  
您將看到許多使用回呼的程式碼範例，並承諾處理 DynamoDB 操作的結果。使用現代 JavaScript 不再需要這種複雜性，開發人員可以利用更簡潔且可讀取的非同步/等待語法進行非同步操作。

**Web 瀏覽器執行時期**  
使用 React 或 React Native 進行建置的 Web 和行動開發人員可以在其專案中使用適用於 JavaScript 的 SDK。使用舊版的 SDK V2，Web 開發人員必須將完整的 SDK 載入瀏覽器，並參考託管於 https://sdk.amazonaws.com/js/ 的 SDK 映像。  
使用 V3 時，您可以使用 Webpack 將所需的 V3 用戶端模組和所有必要的 JavaScript 函數綁定到單一 JavaScript 檔案中，並將其新增至 HTML 頁面 `<head>` 中的指令碼標籤，如 SDK 文件的[瀏覽器指令碼入門](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/getting-started-browser.html)一節所述。

**DAX 資料平面操作**  
適用於 JavaScript V3 的 SDK 支援 Amazon DynamoDB Streams Accelerator (DAX) 資料平面操作。