使用 Azure 逻辑应用的工作流内联添加和运行 JavaScript 代码

适用范围:Azure 逻辑应用(消耗型 + 标准型)

要在 Azure 逻辑应用中使用工作流内联执行自定义集成任务,可以直接在 Azure 门户中从工作流添加和运行简单的 JavaScript 代码片段。 对于此任务,请使用名为执行 JavaScript 代码内联代码操作。 此操作返回代码片段返回中的结果,以便可以在工作流的后续操作中使用该输出。 此操作还具有不同的限制,具体取决于你拥有的是消耗型工作流还是标准工作流,并且最适合具有以下属性的代码片段:

操作 语言 语言版本 运行持续时间 数据大小 其他说明
执行 JavaScript 代码 JavaScript 标准
Node.js 16.x.x

消耗
Node.js 8.11.1

有关详细信息,请参阅标准内置对象
在 5 秒或更短时间内完成。 处理最多 50 MB 的数据。 - 不需要使用该操作不支持的“变量”操作

- 不支持用于运行 JavaScript 的 require() 函数。

要运行不适合这些属性的代码,可以使用 Azure Functions 创建和调用函数

本指南介绍了如何在以 Office 365 Outlook 触发器开头的示例工作流中运行操作。 当新电子邮件到达关联的 Outlook 电子邮件帐户时,工作流将开始运行。 示例代码片段提取含电子邮件正文的任何电子邮件的地址,并将这些地址作为可在后续操作中使用的输出返回。

下图显示了示例工作流中的亮点:

先决条件

  • Azure 帐户和订阅。 如果没有订阅,可以注册 Azure 帐户

  • 要将代码片段添加到的逻辑应用工作流。 工作流须以触发器开头。

    本文的示例使用名为收到新电子邮件时的 Office 365 Outlook 触发器。

    如果没有工作流,请参阅以下文档:

  • 根据你拥有的是消耗型还是标准逻辑应用工作流,查看以下要求:

    • 消耗工作流

      • Node.js 版本 8.11.10

      • 从逻辑应用资源指向集成帐户的链接(空或其他)。

        重要

        请确保使用适合你的用例或方案的集成帐户。

        例如,免费层集成帐户仅适用于探索方案和工作负载,而不适用于生产方案,另外,其使用量和吞吐量有限制,且不附带服务级别协议 (SLA) 的支持。

        其他集成帐户层会产生费用,但附带 SLA 支持,并且提供更高的吞吐量和限制。 详细了解集成帐户层限制定价

    • 标准工作流

添加“执行 JavaScript 代码”操作

  1. Azure 门户中,打开设计器中的消耗逻辑应用工作流。

  2. 在设计器中,按照这些常规步骤将名为“执行 JavaScript 代码”的内联代码操作添加到你的工作流

    此示例将操作添加到 Office 365 Outlook 触发器下面。 默认情况下,该操作包含一些示例代码,包括 return 语句。

    显示包含默认示例代码的“执行 JavaScript 代码”操作的屏幕截图。

  3. 在“代码”框中删除示例代码,然后输入你的代码。 编写要放入方法中的但不带方法签名的代码。

    提示

    当光标位于“代码”框中时,将显示动态内容列表。 虽然稍后将使用此列表,但现在暂时可以忽略该列表并保持为打开状态。 不要选择“隐藏”。

    当你开始键入已识别的关键字时,会显示自动完成列表,以方便你从可用关键字中进行选择,例如:

    显示消耗型工作流、“执行 JavaScript 代码”操作和关键字自动完成列表的屏幕截图。

    以下示例代码片段首先创建一个名为 myResult 变量用于存储某个正则表达式,该表达式指定要在输入文本中匹配的模式。 然后,代码创建一个名为 email 的变量,该变量存储来自触发器输出的电子邮件正文内容。

    显示消耗型工作流、“执行 JavaScript 代码”操作和创建变量的示例代码的屏幕截图。

  4. 在鼠标仍位于“代码”框中时,从打开的动态内容列表中,找到“收到新电子邮件时”部分,然后选择用于引用电子邮件正文的 Body 属性。

    显示消耗型工作流、“执行 JavaScript 代码”操作、动态内容列表和选中的电子邮件“Body”属性的屏幕截图。

    当这些输出与当前处于焦点的编辑框的输入格式匹配时,动态内容列表会显示触发器的输出和前面的任何操作。 此列表使这些输出更易于从工作流使用和引用。 在此示例中,该列表显示 Outlook 触发器的输出,包括电子邮件的 Body 属性。

    选择 Body 属性后,“执行 JavaScript 代码”操作会将令牌解析为只读的 workflowContext JSON 对象,你的代码片段可以将其用作输入。 该 workflowContext 对象包含的属性使代码能够访问工作流中的触发器输出和前面的操作,例如触发器 body 的属性,该属性不同于电子邮件的 Body 属性。 有关 workflowContext 对象的详细信息,请参阅本文后面的使用 workflowContext 对象引用触发器和操作结果

    重要

    如果代码段引用的操作名称包含点运算符 (.),则这些引用必须用方括号 ([]) 和引号 ("") 将这些操作名称括起来,例如:

    // Correct
    workflowContext.actions["my.action.name"].body

    // Incorrect
    workflowContext.actions.my.action.name.body

    此外,在“执行 JavaScript 代码”操作中,需要添加 Actions 参数并将这些操作名称添加到该参数。 有关详细信息,请参阅本文后面的部分:将依赖项作为参数添加到执行 JavaScript 代码操作中

  5. 为了区分从触发器的 body 属性中选择的电子邮件的 Body 属性,将第二个 body 属性重命名为 Body。 在末尾添加结束分号 (;) 以完成代码语句。

    屏幕截图显示消耗型逻辑应用工作流、“执行 JavaScript 代码”操作和带有结束分号的已重命名的“Body”属性。

    执行 JavaScript 代码”操作在语法上不需要 return 语句。 但是,通过包括 return 语句,稍后在工作流的后续操作中可使用 Result 令牌更轻松地引用操作结果。

    在本例中,代码片段通过调用 match() 函数返回结果,该函数在电子邮件消息正文中查找与指定的正则表达式匹配的任何项。 然后,“创建 HTML 表”操作使用 Result 令牌引用“执行 JavaScript 代码”操作的结果,并创建单个结果。

    显示已完成的消耗逻辑应用工作流的屏幕截图。

  6. 完成后,保存工作流。

使用 workflowContext 对象引用触发器和操作输出

从设计器上的代码片段内部,可以使用动态内容列表选择可引用触发器或任何上述操作的输出的令牌。 选择令牌时,“执行 JavaScript 代码”操作会将该令牌解析为只读的 workflowContext JSON 对象。 此对象使代码能够访问触发器、前面任何操作和工作流的输出。 该对象使用以下结构并包括 actionstriggerworkflow 属性,这些属性也是对象:

{
   "workflowContext": {
      "actions": {
         "<action-name-1>": @actions('<action-name-1>'),
         "<action-name-2>": @actions('<action-name-2>')
      },
      "trigger": {
         @trigger()
      },
      "workflow": {
         @workflow()
      }
   }
}

下表包含有关这些属性的详细信息:

属性 类型​​ 说明
actions 对象集合 在代码段运行之前运行的任何先前操作的结果对象。 每个对象都有一个键值对,其中键是操作名称,值等效于使用 @actions('<action-name>') 表达式调用 actions() 函数的结果。

该操作名称与基础工作流定义中显示的操作名称相同,只是将此定义的操作名称中的空格 (" ") 替换成了下划线 (_)。 此对象集合提供对当前工作流实例运行中的操作属性值的访问。
trigger 对象 其结果与调用 trigger() 函数等效的触发器的结果对象。 此对象提供对当前工作流实例运行中的触发器属性值的访问。
workflow 对象 工作流对象,等效于调用 workflow() 函数。 此对象提供对当前工作流实例运行中的属性值(例如工作流名称、运行 ID 等)的访问。

在本文的示例中,workflowContext JSON 对象可能具有来自 Outlook 触发器的以下示例属性和值:

{
   "workflowContext": {
      "trigger": {
         "name": "When_a_new_email_arrives",
         "inputs": {
            "host": {
               "connection": {
                  "name": "/subscriptions/<Azure-subscription-ID>/resourceGroups/<Azure-resource-group-name>/providers/Microsoft.Web/connections/office365"
               }
            },
            "method": "get",
            "path": "/Mail/OnNewEmail",
            "queries": {
               "includeAttachments": "False"
            }
         },
         "outputs": {
            "headers": {
               "Pragma": "no-cache",
               "Content-Type": "application/json; charset=utf-8",
               "Expires": "-1",
               "Content-Length": "962095"
            },
            "body": {
               "Id": "AAMkADY0NGZhNjdhLTRmZTQtNGFhOC1iYjFlLTk0MjZlZjczMWRhNgBGAAAAAABmZwxUQtCGTqSPpjjMQeD",
               "DateTimeReceived": "2019-03-28T19:42:16+00:00",
               "HasAttachment": false,
               "Subject": "Hello World",
               "BodyPreview": "Hello World",
               "Importance": 1,
               "ConversationId": "AAQkADY0NGZhNjdhLTRmZTQtNGFhOC1iYjFlLTk0MjZlZjczMWRhNgAQ",
               "IsRead": false,
               "IsHtml": true,
               "Body": "Hello World",
               "From": "<sender>@<domain>.com",
               "To": "<recipient-2>@<domain>.com;<recipient-2>@<domain>.com",
               "Cc": null,
               "Bcc": null,
               "Attachments": []
            }
         },
         "startTime": "2019-05-03T14:30:45.971564Z",
         "endTime": "2019-05-03T14:30:50.1746874Z",
         "scheduledTime": "2019-05-03T14:30:45.8778117Z",
         "trackingId": "1cd5ffbd-f989-4df5-a96a-6e9ce31d03c5",
         "clientTrackingId": "08586447130394969981639729333CU06",
         "originHistoryName": "08586447130394969981639729333CU06",
         "code": "OK",
         "status": "Succeeded"
      },
      "workflow": {
         "id": "/subscriptions/<Azure-subscription-ID>/resourceGroups/<Azure-resource-group-name>/providers/Microsoft.Logic/workflows/<logic-app-workflow-name>",
         "name": "<logic-app-workflow-name>",
         "type": "Microsoft.Logic/workflows",
         "location": "<Azure-region>",
         "run": {
            "id": "/subscriptions/<Azure-subscription-ID>/resourceGroups/<Azure-resource-group-name>/providers/Microsoft.Logic/workflows/<logic-app-workflow-name>/runs/08586453954668694173655267965CU00",
            "name": "08586453954668694173655267965CU00",
            "type": "Microsoft.Logic/workflows/runs"
         }
      }
   }
}

将依赖项作为参数添加到“执行 JavaScript 代码”操作

在某些方案中,可能需要明确要求“执行 JavaScript 代码”操作包括来自触发器的输出或被代码引用为依赖项的操作。 例如,当代码引用工作流运行时不可用的输出时,必须执行此额外步骤。 在工作流创建期间,Azure 逻辑应用引擎会分析代码片段,以确定代码是否引用任何触发器或操作输出。 如果存在这些引用,引擎会自动包括这些输出。 在工作流运行时,如果在 workflowContext 对象中找不到引用的触发器或操作输出,引擎将生成错误。 若要解决此错误,需要将该触发器或操作添加为“执行 JavaScript 代码”操作的显式依赖项。 另一种需要执行此步骤的方案是 workflowContext 对象引用使用点运算符 (.) 的触发器或操作名称。

若要将触发器或操作添加为依赖项,可以添加适用于“执行 JavaScript 代码”操作的 TriggerActions 参数。 然后,添加触发器或操作名称,因为它们会显示在工作流的基础 JSON 定义中。

注意

不能添加 Variables 操作、循环(例如 For each 或 Until)和迭代索引作为显式依赖项。

如果计划重复使用代码,请确保始终使用代码片段编辑框来引用触发器和操作输出。 这样,代码将包含解析的令牌引用,而不仅仅是添加触发器或操作输出作为显式依赖项。

例如,假设 Office 365 Outlook 连接器的“发送审批电子邮件”操作位于示例工作流中的代码片段之前。 以下示例代码片段包含对此操作的 SelectedOption 输出的引用。

对于此示例,必须只添加 Actions 参数,然后将操作的 JSON 名称 Send_approval_email 添加到参数。 这样一来,你就指定了“执行 JavaScript 代码”操作显式包含“发送审批电子邮件”操作的输出。

查找触发器或操作的 JSON 名称

在开始之前,需要基础工作流定义中的触发器或操作的 JSON 名称。

  • 工作流定义中的名称使用下划线 (_) 而不是空格。

  • 如果操作名称使用点运算符 (.),请包括该运算符,例如:

    My.Action.Name

  1. 在工作流设计器工具栏上选择“代码视图”。 在 actions 对象中,查找操作的名称。

    例如,Send_approval_email 是“发送审批电子邮件”操作的 JSON 名称。

    以 JSON 显示操作名称的屏幕截图。

  2. 若要返回到设计器视图,请在代码视图工具栏上选择“设计器”。

  3. 现在,将 JSON 名称添加到“执行 JavaScript 代码”操作。

将触发器或操作名称添加到“执行 JavaScript 代码”操作

  1. 在“执行 JavaScript 代码”操作中,打开“添加新参数”列表。

  2. 根据方案需求,从参数列表中选择以下参数。

    参数 说明
    操作 将上述操作的输出作为依赖项包含在内。 选择此参数时,系统会提示输入要添加的操作。
    触发器 将触发器的输出作为依赖项包含在内。 选择此参数时,系统会提示是否要包含触发器结果。 所以在“触发器”列表中选择“是”。
  3. 在此示例中,选择 Actions 参数。

    显示“执行 JavaScript 代码”操作和选中的 Actions 参数的屏幕截图。

  4. 在“操作项 - 1”框中,输入操作的 JSON 名称。

    显示“Actions 项 -1”框和该操作的 JSON 名称的屏幕截图。

  5. 若要添加另一个操作名,请选择“添加新项”。

  6. 完成后,保存工作流。

操作参考

有关“执行 JavaScript 代码”操作在使用工作流定义语言的基础工作流定义中的结构和语法的详细信息,请参阅此操作的参考部分

后续步骤