

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

# 使用變數在狀態之間傳遞資料
<a name="workflow-variables"></a>

**使用變數和 JSONata 管理狀態**  
Step Functions 最近新增了變數和 JSONata 來管理狀態和轉換資料。  
進一步了解 部落格文章 使用 [中的變數和 JSONata 簡化開發人員體驗 AWS Step Functions](https://aws.amazon.com/blogs/compute/simplifying-developer-experience-with-variables-and-jsonata-in-aws-step-functions/)   
 以下影片使用 DynamoDB 範例描述 Step Functions 中的變數和 JSONata：  




 透過變數和狀態輸出，您可以在工作流程的步驟之間傳遞資料。

 使用工作流程變數，您可以在步驟中存放資料，並在未來的步驟中擷取該資料。例如，您可以存放 API 回應，其中包含稍後可能需要的資料。相反地，狀態輸出只能用作下一個步驟的輸入。

## 變數的概念概觀
<a name="conceptual-overview-of-variables"></a>

 使用工作流程變數，您可以存放資料以供稍後參考。例如，步驟 1 可能會儲存 API 請求的結果，因此稍後可在步驟 5 中重複使用該請求的一部分。

 在下列案例中，狀態機器會從 API 擷取資料一次。在步驟 1 中，工作流程會將傳回的 API 資料 （每個狀態最多 256 KiB) 存放在變數「x」中，以供後續步驟使用。

 如果沒有變數，您需要透過步驟 1 到步驟 2 到步驟 3 到步驟 4 的輸出來傳遞資料，以在步驟 5 中使用它。如果這些中繼步驟不需要資料該怎麼辦？ 將資料透過輸出和輸入從狀態傳遞到狀態會是不必要的工作。

 透過 變數，您可以存放資料，並在任何未來的步驟中使用。您也可以修改、重新排列或新增步驟，而不會中斷資料的流程。有鑑於變數的彈性，您可能只需要使用**輸出**從平行和映射子工作流程傳回資料，並在狀態機器執行結束時傳回資料。

 ![\[Diagram showing step 1 assigning a value to $x, used in step 5.\]](http://docs.aws.amazon.com/zh_tw/step-functions/latest/dg/images/vars-diag-opt1.png)

 **支援變數的狀態 **

 下列狀態類型支援`Assign`宣告和指派值給變數：*Pass、Task、Map、Parallel、Choice、Watch。*

 若要設定變數，請為 JSON 物件提供變數名稱和值：

```
"Assign": {
  "productName": "product1",
  "count" : 42,
  "available" : true
}
```

 若要參考變數，請在名稱前面加上貨幣符號 (`$`)，例如 `$productName`。

## 預留變數 ：\$1states
<a name="reserved-variable-states"></a>

 Step Functions 會定義名為 的單一預留變數**`$states`**。在 JSONata 狀態下，下列結構會指派給 `$states` 以用於 JSONata 表達式：

```
# Reserved $states variable in JSONata states
$states = {
  "input":       // Original input to the state
  "result":      // API or sub-workflow's result (if successful)
  "errorOutput": // Error Output (only available in a Catch)
  "context":     // Context object
}
```

 在狀態項目上，Step Functions 會將狀態輸入指派給 **`$states.input`**。的值`$states.input`可用於接受 JSONata 表達式的所有欄位。 `$states.input`一律參考原始狀態輸入。

 對於 `Task`、 `Parallel`和 `Map` 狀態：
+ **`$states.result`** 如果成功，則是指 API 或子工作流程的原始結果。
+ **`$states.errorOutput`** 是指 API 或子工作流程失敗時的錯誤輸出。

  `$states.errorOutput` 可用於 `Catch` 欄位的 `Assign`或 `Output`。

在建立、更新`$states.result`或驗證狀態機器時，將攔截無法存取它們`$states.errorOutput`的欄位和狀態中嘗試存取 或 。

`$states.context` 物件會提供有關其特定執行的工作流程資訊，例如 `StartTime`、任務字符和初始工作流程輸入。如需詳細資訊，請參閱 [從 Step Functions 中的內容物件存取執行資料](input-output-contextobject.md)。

## 變數名稱語法
<a name="variable-name-syntax"></a>

 變數名稱遵循 Unicode[® Standard Annex \$131 中所述的 Unicode](https://unicode.org/reports/tr31/) 識別符規則。變數名稱的第一個字元必須是 Unicode ID\$1Start 字元，第二個和後續字元必須是 Unicode ID\$1Continue 字元。變數名稱的長度上限為 80。

 變數名稱慣例類似於 JavaScript 和其他程式設計語言的規則。

## 變數範圍
<a name="variable-scope"></a>

 Step Functions 工作流程使用*工作流程本機範圍*來避免具有變數的競爭條件。

工作流程本機範圍包括狀態機器**狀態**欄位內的所有狀態，但不包括平行或映射狀態內的所有狀態。Parallel 或 Map 狀態內的狀態可以參考外部範圍變數，但它們會建立和維護自己的個別工作流程本機變數和值。

`Parallel` 分支和`Map`反覆運算可以從**外部範圍**存取變數值，但無法從其他並行分支或反覆運算存取變數值。處理錯誤時， 中的 `Assign` 欄位`Catch`可以將值指派給外部範圍內的變數，也就是 Parallel/Map 狀態存在的範圍。

 例外狀況：**分散式映射狀態**目前無法參考外部範圍內的變數。

 如果範圍內的任何狀態為其指派值，則變數存在於範圍內。為了協助避免常見錯誤，內部範圍內指派的變數不能具有與外部範圍內指派的變數相同的名稱。例如，如果最上層範圍將值指派給名為 的變數`myVariable`，則也無法將其他範圍 （在 內`Map`，`Parallel`) 指派給 `myVariable`。

 變數的存取取決於目前的範圍。平行和映射狀態有自己的範圍，但可以存取外部範圍中的變數。

 當平行或映射狀態完成時，其所有變數都將超出範圍並停止存取。使用**輸出欄位**從平行分支和映射反覆運算中傳遞資料。

## ASL 中的指派欄位
<a name="assign-field-in-asl"></a>

 ASL 中的 `Assign` 欄位用於將值指派給一或多個變數。`Assign` 欄位可在每個狀態的頂層 ( `Succeed`和 除外`Fail`)、`Choice`狀態內規則和`Catch`欄位內使用。例如：

```
# Example of Assign with JSONata
"Store inputs": {
    "Type": "Pass",
    "Next": "Get Current Price",
    "Comment": "Store the input desired price into a variable: $desiredPrice",
    "Assign": {
       "desiredPrice": "{% $states.input.desired_price %}",
       "maximumWait": "{% $states.input.max_days %}"
    }
},
```

 `Assign` 欄位接受 JSON 物件。每個最上層欄位都會命名要指派的變數。在先前的範例中，變數名稱為 `desiredPrice`和 `maximumWait`。使用 JSONata 時， `{% ... %}`會指出可能包含變數或更複雜表達式的 JSONata 表達式。如需 JSONata 表達式的詳細資訊，請參閱 [JSONata.org 文件。 ](https://docs.jsonata.org/overview.html)

 使用 **JSONata** 做為查詢語言時，下圖顯示如何平行處理**指派**和**輸出**欄位。請注意隱含：*指派變數值不會影響狀態輸出。 *

 ![\[Diagram showing a comparison of JSONPath and JSONata flow.\]](http://docs.aws.amazon.com/zh_tw/step-functions/latest/dg/images/vars-jsonata.png)

 下列 JSONata 範例`order.product`會從狀態輸入擷取 。變數`currentPrice`會設定為任務結果的值。

```
# Example of Task with JSONata assignment from result
{
   "Type": "Task",
   ...
   "Assign": {
      "product": "{% $states.input.order.product %}",
      "currentPrice": "{% $states.result.Payload.current_price %}"
   },
   "Next": "the next state"
}
```

 注意：**您無法**將值指派給變數的一部分。例如，您可以 `"Assign":{"x":42}`，但無法 `"Assign":{"x.y":42}`或 `"Assign":{"x[2]":42}`。

## 指派欄位中的評估順序
<a name="evaluation-order-in-an-assign-field"></a>

Step Functions 狀態中的所有變數參考都會使用**與狀態項目**相同的值。

先前的事實對於了解 `Assign` 欄位如何將值指派給一或多個變數非常重要。首先，計算新值，然後 Step Functions 會將新值指派給變數。新的變數值將從**下一個**狀態開始提供。例如，請考慮下列`Assign`欄位：

```
# Starting values: $x=3, $a=6

"Assign": {
  "x": "{% $a %}",
  "nextX": "{% $x %}"
}

# Ending values: $x=6, $nextX=3
```

在上述範例中，`x`會同時指派和參考 變數。

請記住，所有表達式都會***先評估***，然後進行指派。而新指派的值將在**下一個**狀態提供。

讓我們詳細介紹範例。假設在先前的狀態下， `$x` 獲指派三 (3) 個值， `$a`獲指派六 (6) 個值。下列步驟說明此程序：

1. 系統會使用所有變數的**目前**值來評估所有表達式。

   表達式`"{% $a %}"`將評估為 6，`"{% $x %}"`並將評估為 3。

1. 接下來，會進行指派：

   `$x` 將獲指派值六 (6) 

   `$nextX` 將獲指派三 (3) 個

 注意：如果先前`$x`未指派 ，則範例會**失敗**，因為 `$x`未定義。 **

 總而言之，Step Functions 會評估**所有**表達式，然後進行指派。變數在 `Assign` 欄位中發生的順序**並不**重要。

## 限制
<a name="limits"></a>

 標準和快速工作流程的單一變數大小上限為 256Kib。

 單一`Assign`欄位中所有變數的合併大小上限也是 256Kib。例如，您可以將 X 和 Y 指派給 128KiB，但無法在相同`Assign`欄位中將 X 和 Y 指派給 256KiB。

 所有存放變數的總大小不能超過每次執行 10MiB。

## 在 JSONPath 狀態中使用變數
<a name="using-variables-in-jsonpath-states"></a>

 變數也可用於使用 JSONPath 查詢語言的狀態。

 您可以在任何接受 JSONpath 表達式 ( `$.`或 `$$.` 語法） 的欄位中參考變數，但 除外`ResultPath`，它會指定狀態輸入中的位置以注入狀態的結果。變數無法在 中使用`ResultPath`。

 在 JSONPath 中，`$`符號是指「目前」值，並`$$`代表狀態內容物件。JSONPath 表達式的開頭可以是 ，`$.`如 所示`$.customer.name`。您可以使用 存取內容`$$.`，如 所示`$$.Execution.Id`。

 若要參考變數，您也可以在變數名稱之前使用 `$`符號，例如 `$x`或 `$order.numItems`。

 在接受內部函數的** JSONPath** 欄位中，變數可用於引數，例如 `States.Format('The order number is {}', $order.number)`。

 下列圖表說明 **JSONPath** 任務中的指派步驟與 ResultSelector 同時在 中發生的方式：

 ![\[Logical diagram of a state that uses JSONPath query language.\]](http://docs.aws.amazon.com/zh_tw/step-functions/latest/dg/images/vars-jsonpath.png)

 **在 JSONPath 中指派變數**

 JSONPath 變數指派的行為類似於承載範本。以 結尾的欄位`.$`表示值是 JSONPath 表達式，Step Functions 會在狀態機器執行期間評估為值 （例如： `$.order..product`和 `$.order.total`)。

```
# Example of Assign with JSONPath
{
  "Type": "Task",
  ...
  "Assign": {
    "products.$": "$.order..product",
    "orderTotal.$": "$.order.total"
  },
  "Next": "the next state"
}
```

 對於 JSONPath 狀態， `$` `Assign` 欄位中的 值取決於狀態類型。在 `Task,` `Map`中， `Parallel` 狀態`$`是指 API/子工作流程結果。在 `Choice`和 `Wait` 狀態中， `$`是指*有效的輸入*，即 之後的值`InputPath`已套用至狀態輸入。對於 `Pass`， `$`是指結果，無論是由 `Result` 欄位還是 `InputPath`/`Parameters` 欄位產生。

 下列 JSONPath 範例會將 JSON 物件指派給 `details`變數、將 JSONPath 表達式的結果`$.result.code`指派給 `resultCode`，並將 JSONPath 表達式的結果`States.Format('Hello {}', $customer.name)`指派給 `message`。如果處於 `Task` 狀態，則 `$` 中的 `$.order.items`和 `$.result.code`會參考 API 結果。`startTime` 變數的指派值來自內容物件 `$$.Execution.StartTime`。

```
"Assign": {
   "details": {
      "status": "SUCCESS",
      "lineItems.$": "$.order.items"
   },
   "resultCode.$": "$.result.code",
   "message.$": "States.Format('Hello {}', $customer.name)",
   "startTime.$": "$$.Execution.StartTime"
}
```