Pylon.bot中使用KVNamespace时Promise<Json>无法赋值给Json类型参数的问题咨询
Pylon.bot中使用KVNamespace时Promise无法赋值给Json类型参数的问题咨询
我完全懂你现在碰到的困扰——在Pylon.bot里用KVNamespace做消息历史滚动存储的时候,get方法返回的Promise<Json>没法直接传给put,编辑器直接报类型不匹配的错误,明明看起来都是Json相关的类型,怎么就不行了呢?
问题根源
其实核心原因很简单:channelMessages.get()是异步操作,它不会直接返回你要的Json值,而是返回一个Promise<Json>对象——这是JavaScript里处理异步任务的标准方式,用来表示“这个操作还在进行中,等完成后会给你实际结果”。而put()方法需要的是实际的Json值,不是一个“待完成的任务承诺”,直接把Promise传进去自然会报类型不兼容的错误。
你现在的代码里直接写channelMessages.put("9", channelMessages.get("8")),本质上是把一个Promise对象当成了要存储的值,这肯定不符合put()的参数要求。
解决方案
好在你的事件处理函数已经声明了async,刚好可以用await关键字来等待Promise完成,拿到实际的Json值再传给put()。另外还要注意,因为你是要按顺序把旧值依次后移(8→9、7→8…1→2,再把新消息存到1),得先把所有旧值都读取出来再执行更新,不然前面的put会覆盖还没读取的旧值,导致数据错误。
优化后的代码示例
var channelMessages = new pylon.KVNamespace("chmsg"); discord.on('MESSAGE_CREATE', async (message) => { if (!(message instanceof discord.GuildMemberMessage)) { return; } // 测试用的触发条件,上线时可以移除 if (message.content.toLowerCase().includes('ayy') && (message.channelId == "1392115752990933022")) { // 先批量读取1-8的当前值,用Promise.all提升效率 const keys = ["1", "2", "3", "4", "5", "6", "7", "8"]; const [val1, val2, val3, val4, val5, val6, val7, val8] = await Promise.all( keys.map(key => channelMessages.get(key)) ); // 从后往前执行更新,避免覆盖未读取的旧值 await channelMessages.put("9", val8); await channelMessages.put("8", val7); await channelMessages.put("7", val6); await channelMessages.put("6", val5); await channelMessages.put("5", val4); await channelMessages.put("4", val3); await channelMessages.put("3", val2); await channelMessages.put("2", val1); await channelMessages.put("1", message.content); // 这里就可以用fetch()把存储的数据同步到其他服务器了 // 比如: // await fetch("你的服务器地址", { // method: "POST", // body: JSON.stringify({ messageHistory: [val1, val2, val3, val4, val5, val6, val7, val8, message.content] }), // headers: { "Content-Type": "application/json" } // }); } });
额外说明
- 为什么要先批量读取所有旧值?
如果你边读边写(比如先get(8)再put(9, 结果),然后get(7)再put(8, 结果)),虽然也能工作,但批量读取+批量更新的方式更高效,也能避免因为异步顺序问题导致的数据混乱。 - 为什么
put()前面也要加await?put()本身也是异步操作,加await可以确保每一步存储操作完成后再进行下一个,避免并发更新导致的顺序错误。 - 如果不用
await,还可以用.then()链式调用,但await的写法更直观,和同步代码逻辑差不多,更易读。
内容来源于stack exchange
相关产品推荐
相关产品推荐

