slack - 松弛螺栓清除视图堆栈
问题描述
在 view_submission 类型中,我设置 ack 来清除堆栈,如下所示:
await submissionAck({ response_action: 'clear' } as 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.
但这并不能告诉我太多。那根弦是什么?那是一个功能吗?它应该怎么做?
对不起,noobish 问题,感谢您的帮助!
解决方案
我将尝试以相反的顺序回答这些问题,因为我认为这可能最有意义。
那根弦是什么?那是一个功能吗?它应该怎么做?(参考
app.view()
)
创建 Modal 时,通常使用callback_id
. 您可以在视图有效负载的文档中查看该属性的描述。
那句话试图说这是您如何为使用callback_id
set to创建的视图收听视图提交"some_callback_id"
:
app.view('some_callback_id', async () => {
/* listener logic goes here */
})
注意:如果您想要相同的函数来处理许多视图的视图提交,您也可以使用正则表达式 - 视图callback_id
都遵循相同的模式。但是正则表达式是一个非常高级的案例,我认为我们现在不应该担心它。
要创建模态,请使用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 */ }],
},
})
})
})
接下来,不要在另一个 listener 中处理视图提交。当您这样做时,每次外部侦听器运行时,您都在(重新)注册要运行的视图提交侦听器。所以第一次运行一次,第二次运行两次,第三次运行三次。这解释了为什么堆栈跟踪会告诉您它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
。在这些接口之内,BlockAction
确实InteractiveMessage
有一个trigger_id
属性,但DialogSubmitAction
没有。因此就 TypeScript 而言,它不能确定该属性是否body.trigger_id
存在。您可能知道您正在处理的操作是 a 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
参数是 type ViewSubmitAction | ViewClosedAction
。使用clear
响应动作对 a 没有意义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
以同样的方式进行通用化。
推荐阅读
- git - 从多个存储库移动到一个单一存储库(在 GitLab 上)
- javascript - 使用 Jquery 提交模式时更改元素
- java - 定时器任务仅在 Spring Boot 中服务器重启后运行
- vba - 将 Access 表单中的 DefaultValue 设置为表的最后一条记录
- python - 句子比较:如何突出差异
- oracle - PLS-00103:尝试使用序列递增值时遇到符号 DECLARE/EOF
- python - python电报bot api inlinekeyboardbutton没有得到callback_data
- c# - 使用 xslt 模板将多个图像添加到 docx 文件
- dart - Dart 将类型传递给函数失败
- xamarin - 在 Fabulous (F#) UWP 应用程序中使用 Xamarin Essentials 文件选择器