【问题标题】:Slack Bolt Clearing view stack松弛螺栓清除视图堆栈
【发布时间】:2020-09-22 15:52:15
【问题描述】:

在 view_submission 类型中,我设置 ack 来清除堆栈,如下所示:

await submissionAck({ response_action: 'clear' } as any)

第一个问题 - 为什么我必须将其转换为 any?没有它,代码会抛出错误

Argument of type '{ response_action: "clear"; }' is not assignable to parameter of type '(ViewUpdateResponseAction & void) | (ViewPushResponseAction & void) | (ViewClearResponseAction & void) | (ViewErrorsResponseAction & void) | undefined'.Type '{ response_action: "clear"; }' is not assignable to type 'ViewClearResponseAction & void'.
Type '{ response_action: "clear"; }' is not assignable to type 'void'.

第二个问题 - 堆栈似乎没有被清除。当我第一次提交模态时没关系,但如果我下次尝试它会抛出:

[ERROR]  bolt-app { Error: The receiver's `ack` function was called multiple times.
    at ack (/home/ec2-user/metrics/node_modules/@slack/bolt/src/ExpressReceiver.ts:147:17)
    at /home/ec2-user/metrics/app/actions.ts:43:17
    at Generator.next (<anonymous>)
    at /home/ec2-user/metrics/app/actions.ts:11:71
    at new Promise (<anonymous>)
    at __awaiter (/home/ec2-user/metrics/app/actions.ts:7:12)
    at app.view (/home/ec2-user/metrics/app/actions.ts:40:70)
    at process_1.processMiddleware (/home/ec2-user/metrics/node_modules/@slack/bolt/src/App.ts:660:19)
    at invokeMiddleware (/home/ec2-user/metrics/node_modules/@slack/bolt/src/middleware/process.ts:36:12)
    at next (/home/ec2-user/metrics/node_modules/@slack/bolt/src/middleware/process.ts:28:21)
    at Array.<anonymous> (/home/ec2-user/metrics/node_modules/@slack/bolt/src/middleware/builtin.ts:201:11)
    at invokeMiddleware (/home/ec2-user/metrics/node_modules/@slack/bolt/src/middleware/process.ts:27:47)
    at next (/home/ec2-user/metrics/node_modules/@slack/bolt/src/middleware/process.ts:28:21)
    at Array.exports.onlyViewActions (/home/ec2-user/metrics/node_modules/@slack/bolt/src/middleware/builtin.ts:110:11)
    at invokeMiddleware (/home/ec2-user/metrics/node_modules/@slack/bolt/src/middleware/process.ts:27:47)
    at Object.processMiddleware (/home/ec2-user/metrics/node_modules/@slack/bolt/src/middleware/process.ts:39:10) code: 'slack_bolt_receiver_ack_multiple_error' }

有什么想法吗?这就是我如何称呼这些视图:(顺便说一句,第三个问题 - 为什么我必须将 body 转换为 BlockAction?否则它会引发 trigger_id 不存在的错误)

  app.action('modify', async ({ body, ack }) => {
    await ack()
    await authenticate(body.team.id, async (customer: Customer) => {
      await app.client.views.open({
        trigger_id: (body as BlockAction).trigger_id,
        token: 'token',
        view: modificationModal,
      })
      app.view(
        {
          type: 'view_submission',
          callback_id: 'yay',
        },
        async ({ body: submissionBody, ack: submissionAck, view }) => {
          const receivedValues = submissionBody.view.state.values
          await submissionAck({ response_action: 'clear' } as any)
        },
      )
    })
  })

我知道在文档中是这样的:

view() requires a callback_id of type string or RegExp.

但这并不能告诉我太多。那根弦是什么?那是一个功能吗?它应该怎么做?

很抱歉提出了一个愚蠢的问题,感谢您的帮助!

【问题讨论】:

    标签: slack slack-api bolt


    【解决方案1】:

    我将尝试以相反的顺序回答这些问题,因为我认为这可能最有意义。

    那个字符串是什么?那是一个功能吗?它应该怎么做? (参考app.view()

    创建模态框时,通常使用callback_id 创建它。您可以在 view payload 的文档中查看该属性的说明。

    这句话试图说这就是您如何为使用callback_id 设置为"some_callback_id" 创建的视图收听视图提交:

    app.view('some_callback_id', async () => {
      /* listener logic goes here */
    })
    

    注意:如果您想要相同的函数来处理多个视图的视图提交,您也可以使用正则表达式——callback_ids 的视图都遵循相同的模式。但是正则表达式是一个非常高级的案例,我认为我们现在不应该担心它。

    要创建模态框,您可以使用views.open 方法,这就是您首先要设置callback_id 的地方。我将提出改进建议。所有 Web API 方法都可以在侦听器中作为 client 参数上的方法使用。然后您无需担心添加token。下面是一个使用这个的例子:

    // Add the `client` argument
    app.action('modify', async ({ body, ack, client }) => {
      await ack()
      await authenticate(body.team.id, async (customer: Customer) => {
        // Remove `app.`
        await client.views.open({
          // Let's come back to this cast later
          trigger_id: (body as BlockAction).trigger_id,
          // Not sure what's in modificationModal, but to illustrate, I used a literal
          view: {
            // *** Setting the callback_id ***
            callback_id: 'modify_submission',
            title: {
              type: 'plain_text',
              text: 'Modify something'
            },
            blocks: [{ /* add your blocks here */ }],
          },
        })
      })
    })
    

    接下来,不要在另一个侦听器中处理视图提交。当您这样做时,每次外部侦听器运行时,您都在(重新)注册要运行的视图提交侦听器。所以第一次运行一次,第二次运行两次,第三次运行三次。这就解释了为什么堆栈跟踪告诉您ack() 被多次调用。相反,只需在该侦听器之外处理视图提交。两个交互之间的“链接”信息是callback_id。以前面的例子为基础:

    // Further down in the same file, at the same level as the previous code
    // *** Using the callback_id we set previously ***
    app.view('modify_submission', async ({ body, ack, view }) => {
      const receivedValues = body.view.state.values
      // Let's come back to this cast later
      await ack({ response_action: 'clear' } as any)
    })
    

    好的,这一切都应该有效,但现在让我们谈谈演员表。当您使用app.action() 处理操作时,body 参数的类型为BlockAction | InteractiveMessage | DialogSubmitAction。在这些接口中,BlockActionInteractiveMessage 确实具有 trigger_id 属性,但 DialogSubmitAction 没有。所以就 TypeScript 而言,它不能确定属性 body.trigger_id 是否存在。您可能知道您正在处理的操作是 BlockAction(假设它是),但 TypeScript 不知道!但是,Bolt 旨在允许用户通过使用泛型参数为 TypeScript 提供更多信息。这是第一个示例的一部分,已修改为使用泛型参数。

    import { BlockAction } from '@slack/bolt';
    
    app.action<BlockAction>('modify', async ({ body, ack, client }) => {
       // `body` is now typed as a BlockAction, and therefore body.trigger_id is a string
    });
    

    app.view() 和泛型参数的情况非常相似。这一次,body 参数的类型是 ViewSubmitAction | ViewClosedAction。使用clear 响应操作对ViewClosedAction 没有意义,因此我们需要再次约束类型。没错,泛型参数不仅仅与body 的类型相关联,它实际上可以更改(约束)任何侦听器参数!在这种情况下,泛型参数会更改ack() 的类型。

    import { ViewSubmitAction } from '@slack/bolt';
    
    app.view<ViewSubmitAction>('modify_submission', async ({ body, ack, view }) => {
      // No errors now
      await ack({ response_action: 'clear' });
    });
    

    最后说明:您使用约束对象编写视图提交处理程序的方式({ type: 'view_submission', callback_id: 'yay' } 似乎您已经为 TypeScript 提供了足够的信息来约束侦听器参数的类型。这实际上适用于 app.action({ type: 'block_actions', ... }, ...),因为我们将ActionConstraints 定义为泛型。这是Bolt 可以改进的领域,只需以相同的方式使ViewConstraints 泛型即可。

    【讨论】:

    • 这个答案回答了我所有的问题,非常感谢!您的解释使一切变得更容易理解。我修复了我的代码,效果很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-24
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    相关资源
    最近更新 更多