バージョン情報
discord.js : v14.3.0
node : v16.13.2
npm : v8.1.2
Promise { < pending > } について
discordのbotを開発している際、下記のようなコードを書くとある結果が返ってきます。
client.on('ready', () => {
console.log(client.channels.cache.get("チャンネルのID").messages.fetch("メッセージのID"));
});
結果
Promise { <pending> }
ちなみに上記の処理は、特定のチャンネルにある特定のメッセージの内容をメッセージIDを使って取得する時などに使います。
<ref *1> Message {
channelId: '00000000000',
guildId: '00000000000',
id: '00000000000',
createdTimestamp: 00000000000,
type: 0,
system: false,
content: 'メッセージIDからメッセージを取得出来る処理を書きます。',
author: User {
id: '00000000000',
bot: false,
system: false,
flags: UserFlagsBitField { bitfield: 0 },
username: 'Maki-engineer',
discriminator: '0000',
avatar: 'fflajflkalkjaejfifeijf',
banner: undefined,
accentColor: undefined
},
pinned: false,
tts: false,
nonce: null,
embeds: [],
components: [],
attachments: Collection(0) [Map] {},
stickers: Collection(0) [Map] {},
editedTimestamp: null,
reactions: ReactionManager { message: [Circular *1] },
mentions: MessageMentions {
everyone: false,
users: Collection(0) [Map] {},
roles: Collection(0) [Map] {},
_members: null,
_channels: null,
_parsedUsers: null,
crosspostedChannels: Collection(0) [Map] {},
repliedUser: null
},
webhookId: null,
groupActivityApplication: null,
applicationId: null,
activity: null,
flags: MessageFlagsBitField { bitfield: 0 },
reference: null,
interaction: null
}
理想としてはこんな感じでMessageの内容が返ってきてほしいのですが、返ってくるのはPromise { < pending > }のみ。
どのように書けばMessageの内容が返ってくるのでしょうか。
非同期処理を行う
Messageの内容が返ってくるようにしたい場合、非同期処理を行っていきます。
before
client.on('ready', () => {
console.log(client.channels.cache.get("チャンネルのID").messages.fetch("メッセージのID"));
});
after
client.on('ready', () => {
client.channels.cache.get("チャンネルのID").messages.fetch("メッセージのID")
.then((message) => console.log(message));
});
このようにして書くことで、Messageの内容が返ってきます。
ちなみに .catch を追加することで、エラーが起こった時の処理を行うことも出来ます。
before
client.on('ready', () => {
client.channels.cache.get("チャンネルのID").messages.fetch("メッセージのID")
.then((message) => console.log(message));
});
after
client.on('ready', () => {
client.channels.cache.get("チャンネルのID").messages.fetch("メッセージのID")
.then((message) => console.log(message))
.catch((error) => console.log(error));
});
非同期処理を行うメリット
非同期処理を行うメリットとしては
・ Promise { < pending > } が返ってこない。
・ 存在しないメッセージIDやチャンネルIDを指定してもbotが停止することなく起動し続けることが出来るようになる。
とりあえず思いつくのはここらへんかなと思います。
2つめに関しては、例えば入力されたコマンドに対する処理を行った後に、数秒後に入力されたコマンドを自動で削除する時などに真価を発揮します。
client.on('messageCreate', (message) => {
if(message.content === "Hello"){
message.reply("world!");
setTimeout(() => message.delete(), 20000);
}
});
試しに簡単な処理を書いてみました。「Hello」とメッセージを送ったら、「world!」と返事をして、20秒後に自動で「Hello」を削除する処理になっています。こちらの処理は基本的にはエラーが起こることはないのですが、もし20秒以内に「Hello」と入力をした人が自分でメッセージを削除した場合どうなると思いますか?
結果はこうなります。
DiscordAPIError[10008]: Unknown Message
at SequentialHandler.runRequest (C:\Users\ryohe\discord-bot\node_modules\@discordjs\rest\dist\lib\handlers\SequentialHandler.cjs:293:15)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async SequentialHandler.queueRequest (C:\Users\ryohe\discord-bot\node_modules\@discordjs\rest\dist\lib\handlers\SequentialHandler.cjs:99:14)
at async REST.request (C:\Users\ryohe\discord-bot\node_modules\@discordjs\rest\dist\lib\REST.cjs:52:22)
at async MessageManager.delete (C:\Users\ryohe\discord-bot\node_modules\discord.js\src\managers\MessageManager.js:245:5)
at async Message.delete (C:\Users\ryohe\discord-bot\node_modules\discord.js\src\structures\Message.js:767:5) {
rawError: { message: 'Unknown Message', code: 10008 },
code: 10008,
status: 404,
method: 'DELETE',
url: 'https://discord.com/api/v10/channels/1017805557354205194/messages/1027131823509221457',
requestBody: { files: undefined, json: undefined }
}
要するに「削除するメッセージがないでちゅ!」て言ってるんですね。
一見このエラーはif文を使って「削除するメッセージはまだ存在するか」て書いて、存在する場合は削除するみたいな感じで書くことで回避することが出来そうですが、残念ながら回避することは出来ません。(実践済み)
そこで非同期処理の出番です。
before
client.on('messageCreate', (message) => {
if(message.content === "Hello"){
message.reply("world!");
setTimeout(() => message.delete(), 20000);
}
});
after
client.on('messageCreate', (message) => {
if(message.content === "Hello"){
message.reply("world!");
setTimeout(() => {
message.delete()
.then((deleteMessage) => console.log("削除することが出来ました"))
.catch((error) => console.log("こちらのメッセージは既に削除されていました。"));
}, 20000);
}
});
このように書くことで、20秒以内にメッセージが削除されちゃっても、botが停止することなく起動し続けることが出来るようになります。
最後に
個人的にPromise { < pending > }が返ってこないようにするための方法、手動で削除された場合は自動でメッセージを削除する処理を行う方法はかなり苦戦したため、非同期処理について学ぶことが出来て良かったです。(asyncとかはまだ使いこなせていませんが...)
まだまだ駆け出しエンジニアのため、間違いなどがあった場合は遠慮なく指摘お願いしますm(_ _)m