Vk-io: [bug] vk.api 发送参数等于 undefined

创建于 2020-08-27  ·  18评论  ·  资料来源: negezor/vk-io

嘿!
简而言之,使用明确指定值undefined的参数调用任何API 都会导致它被转移到 VK。 下面是一个例子。

你做了什么?

await ctx.send("it'll fail", {
    keyboard: undefined
});

ctx - 事件上下文message_new

Снимок экрана 2020-08-28 в 00 53 43

你期望会发生什么?

不应传递值为undefined参数,与省略它们完全相同。

实际结果如何?

VK-IO 将undefined成字符串并提供给服务器。

版本

| 包装 | 版本 |
| ---------------------------------- | -------- |
| vk-io | 4.0.1 |
| node | 12.17.0 |
| TypeScript | 4.0.2 |
| yarn | 1.22.4 |

vk-io

所有18条评论

不,等等,它有点不工作。 给你解释一下?

来吧,有什么小问题?

使用 URLSearchParams 发送参数

const params = {
   message: 'hello',
   keyboard: undefined
};

console.log(new URLSearchParams(params));
// Выведет: URLSearchParams { 'message' => 'hello', 'keyboard' => 'undefined' }

@isinkin是的,但我已经在 PR 中写过这是一个错误,因为 TypeScript 根本没有任何区别,没有指定参数或指定了值undefined ,但在运行时这已经导致 API 错误。 这是某种直接的陷阱。

@zardoy为什么这是一个错误?

const obj = {
  key: undefined,
}

const properties = Object.getOwnPropertyNames(obj)

console.log(properties)

声明了属性,它的类型是未定义的,当转换为字符串时,得到字符串'undefined'。
ts 不能正常工作的事实已经适用于 ts,运行时通常在 v8 上,并且它只支持 javascript。

const obj = {
  key: undefined,
}

const properties = Object.getOwnPropertyNames(obj)

console.log(properties)

没错,但为什么会发生这种转变? 毕竟,如果我们要显式传递这样内容的字符串,为什么不显式地将字符串作为参数传递呢?

vk.api.messages.send({
    message: "undefined" // - так ок
});

也许你是对的,这不是一个错误,而只是一个陷阱,因为当你明确指定undefined时 ts 不会引发编译错误。 但是,我在 PR 中的建议是,当我们完全省略参数并指定undefined将是相同的,因为并非总是如此

Sori,我关闭了,我现在将添加。

@zardoy我明白你的意思。

当然你写的东西像

let someVariable;

const query = {
  key: someVariable,
}

send(query)

我认为这个问题出在用户方面,您需要以不同的方式编写,并且使用此 pr 您会破坏向后兼容性。

我认为这个问题出在用户方面,您需要以不同的方式编写,并且使用此 pr 您会破坏向后兼容性。

我同意。

看看狗被埋在哪里(一个更说明性的例子):

  • 我不能那样拼写
    Снимок экрана 2020-08-28 в 13 39 24

  • 我已经可以做到了
    Снимок экрана 2020-08-28 в 13 39 59

ts 会发誓,尽管请求实际上是一样的。 对用户来说只是一个陷阱

@zardoy所以如果你不想传递这个参数就不要写任何东西,它会按照你想要的方式工作

vk.api.messages.send()

存在相当不匹配的行为, JSON.stringify() undefined将被遗漏。 而URLSearchParams将所有内容都引导到一个字符串。 这不会破坏向后兼容性,因为检查的是undefined ,而不是"undefined"

但是现在我们将以undefined的形式在聊天中丢失有趣的消息 :)

@negezor关于我的意思是这样的消息,有人可能在他们想要打印这样的文本时使用了未定义的类型)

upd:好吧,不是未定义,而是在某些情况下会抛出异常,例如,当消息为空时。

你为什么在参数中指定 undefined ?

显式指示是一个简化示例,仅用于理解目的。 实际上,这个值可以来自一个函数,当对象被合并时,也可以来自很多其他地方。 这是 PR 的一个例子:

await ctx.send("Hey` there!", {
    keyboard: await getKeyboardToSend() //undefined | KeyboardBuilder - соответствие типов, но ошибка ругается API
});

在这里我将它用作后备类型,这意味着您不需要显示键盘

URLSearchParams 收集未定义的事实可能更灵活和正确,但不太方便。

我对vkapi和这个lib的资源不太了解,我不能说是否有问题,但如果一个库中确实存在不同行为的问题,那么应该解决这个问题。

我猜您可以直接传递请求的主体,然后使用 JSON.stringify 将其转换为 JSON,与 URLSearchParams 不同,它会截断 undefined,这会让用户感到困惑。

URLSearchParams 收集未定义的事实可能更灵活和正确,但不太方便。

@talentumtuum不太同意,我什至可以举一个来自另一个非常大的库的例子。
有这样一个棱镜库(通过它你可以对数据库进行查询)。 这是他们的一个例子:

const hisNotes = await prisma.userNote.findMany({
    where: {
        userName: "Dmitriy" // вернет записки только дмитрия
    }
});
const allNotes = await prisma.userNote.findMany({
    where: {
        userName: undefined // не вернет записки пользователя "undefined"
    }
});
// это равносильно
allNotes = await prisma.userNote.findMany({ });

upd:好吧,不是未定义,而是在某些情况下会抛出异常,例如,当消息为空时。

我同意,想象一下,如果机器人垃圾邮件在任何命令上“未定义”。 比沉默的废话更好的例外xd

upd:也许他们至少会在日志中看到它,但他们会修复它

不过,我认为一个错误比一个有问题的帖子更好。 在像Sentry这样的工具中undefined不是。

这也修复了URLSearamParamsJSON.stringify()之间的不明显行为,固定在https://github.com/negezor/vk-io/commit/1026d333a07ff50423100f331e74a8041e2f567d ,发布于4.0.2

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

Jengas picture Jengas  ·  15评论

ogmishanya picture ogmishanya  ·  4评论

Bobrovskih picture Bobrovskih  ·  3评论

T1MOXA picture T1MOXA  ·  20评论

alexey2baranov picture alexey2baranov  ·  8评论