async function
should have await
expression JS-0116async
function without any await
expressions23 * @param {Client} client
24 */
25
26 async execute(interaction, client) {27 if (interaction.isStringSelectMenu()) {28 if (interaction.user.bot) return;29 const command = client.selectMenus.get(interaction.customId);30 if (!command) {31 interaction.reply({32 ephemeral: true,33 content: "Failed to execute select menus!"34 });35 };363738 //===============< DEVELOPER ONLY >===============\\39 if (command.authorOnly && !interaction.user.id) {40 interaction.reply({41 ephemeral: true,42 content: "This action can only be used by Author!"43 });44 };4546 //===============< EXECUTE CMD >===============\\47 try {48 command.execute(client, interaction);49 } catch (error) {50 errorCmdLogsSelect(client, interaction, error)51 console.log(`${color.bold.red(`[INTERACTION > SELECTION: ERROR]`)} ` + `${error}`.bgRed);52 };53 };54 }55};
56
57/**
async
function without any await
expressions23 * @param {Client} client
24 */
25
26 async execute(interaction, client) {27 if (interaction.isModalSubmit()) {28 if (interaction.user.bot) return;29 const command = client.modalForms.get(interaction.customId);30 if (!command) {31 interaction.reply({32 ephemeral: true,33 content: "Failed to show modal!"34 });35 };3637 //===============< EXECUTE CMD >===============\\38 try {39 command.execute(client, interaction);40 } catch (error) {41 errorCmdLogsModal(client, interaction, error)42 console.log(`${color.bold.red(`[INTERACTION > MODAL: ERROR]`)} ` + `${error}`.bgRed);43 };44 };45 }46};
47
48/**
async
function without any await
expressions 24 * @param {Client} client
25 */
26
27 async execute(interaction, client) { 28 //==================< CHAT INPUT >==================\\ 29 if (interaction.isChatInputCommand()) { 30 if (interaction.user.bot) return; 31 const command = client.slashCommands.get(interaction.commandName); 32 if (!command) { 33 interaction.reply({ 34 ephemeral: true, 35 content: "This command is outdated!" 36 }); 37 }; 38 39 //===============< DEVELOPER ONLY >===============\\ 40 if (command.devOnly && !Config.DEVELOPER.OWNER.includes(interaction.user.id)) { 41 interaction.reply({ 42 ephemeral: true, 43 content: "This command can only be used by Developer!" 44 }); 45 }; 46 47 //===============< GUILD ONLY >===============\\ 48 if (command.guildOnly && !Guilds.includes(interaction.guild.id)) { 49 interaction.reply({ 50 ephemeral: true, 51 content: "This command can only be used by Official Server!" 52 }); 53 }; 54 55 //===============< VOICE ONLY >===============\\ 56 if (command.voiceOnly) { 57 const GME = interaction.guild.members.cache.get(client.user.id); 58 if (!interaction.member.voice.channelId) { 59 interaction.reply({ 60 ephemeral: true, 61 content: "This command can only be used in voice channel, and you are not connected to an audio channel!" 62 }); 63 } else if (GME.voice.channelId !== interaction.member.voice.channelId) { 64 interaction.reply({ 65 ephemeral: true, 66 content: "This command can only be used in voice channel, and you are not on the same audio channel as me!" 67 }); 68 }; 69 }; 70 71 //===============< NSFW ONLY >===============\\ 72 if (command.nsfwOnly && !interaction.channel.nsfw) { 73 interaction.reply({ 74 ephemeral: true, 75 content: "This command can only be used in NSFW channel!" 76 }); 77 }; 78 79 //===============< DISABLED CMD >===============\\ 80 if (command.toggleOffCmd && !Config.DEVELOPER.OWNER.includes(interaction.user.id)) { 81 interaction.reply({ 82 ephemeral: true, 83 content: "This command has been disabled by developer!" 84 }); 85 }; 86 87 //===============< MAINTENANCE CMD >===============\\ 88 if (command.maintenanceCmd && !Config.DEVELOPER.OWNER.includes(interaction.user.id)) { 89 interaction.reply({ 90 ephemeral: true, 91 content: "This command has been maintenance by developer!" 92 }); 93 }; 94 95 //===============< COOLDOWN CMD >===============\\ 96 if (onCoolDownInt(interaction, command) && !Config.DEVELOPER.OWNER.includes(interaction.user.id)) { 97 interaction.reply({ 98 ephemeral: true, 99 content: `Please wait \`${onCoolDownInt(interaction, command).toFixed(1)}\` before using the \`${interaction.commandName}\` command again!`100 });101 };102103 //===============< EXECUTE CMD >===============\\104 try {105 command.execute(client, interaction);106 } catch (error) {107 errorCmdLogsInt(client, interaction, error)108 console.log(`${color.bold.red(`[INTERACTION > SLASH: ERROR]`)} ` + `${error}`.bgRed);109 };110 };111112 //==================< AUTO COMPLETE >==================\\113 if (interaction.isAutocomplete()) {114 const command = client.slashCommands.get(interaction.commandName);115 command.autocomplete(client, interaction);116 };117 }118};
119
120/**
async
function without any await
expressions 24 * @param {ChatInputCommandInteraction} interaction
25 */
26
27 async execute(interaction, client) { 28 if (interaction.isContextMenuCommand()) { 29 if (interaction.user.bot) return; 30 const command = client.slashCommands.get(interaction.commandName); 31 if (!command) { 32 interaction.reply({ 33 ephemeral: true, 34 content: "This command is outdated!" 35 }); 36 }; 37 38 //===============< DEVELOPER ONLY >===============\\ 39 if (command.devOnly && !Config.DEVELOPER.OWNER.includes(interaction.user.id)) { 40 interaction.reply({ 41 ephemeral: true, 42 content: "This command can only be used by Developer!" 43 }); 44 }; 45 46 //===============< GUILD ONLY >===============\\ 47 if (command.guildOnly && !Config.SERVER_ID.OFFICIAL.includes(interaction.guild.id)) { 48 interaction.reply({ 49 ephemeral: true, 50 content: "This command can only be used by Official Server!" 51 }); 52 }; 53 54 //===============< VOICE ONLY >===============\\ 55 if (command.voiceOnly) { 56 const GME = interaction.guild.members.cache.get(client.user.id); 57 if (!interaction.member.voice.channelId) { 58 interaction.reply({ 59 ephemeral: true, 60 content: "This command can only be used in voice channel, and you are not connected to an audio channel!" 61 }); 62 } else if (GME.voice.channelId !== interaction.member.voice.channelId) { 63 interaction.reply({ 64 ephemeral: true, 65 content: "This command can only be used in voice channel, and you are not on the same audio channel as me!" 66 }); 67 }; 68 }; 69 70 //===============< NSFW ONLY >===============\\ 71 if (command.nsfwOnly && !interaction.channel.nsfw) { 72 interaction.reply({ 73 ephemeral: true, 74 content: "This command can only be used in NSFW channel!" 75 }); 76 }; 77 78 //===============< DISABLED CMD >===============\\ 79 if (command.toggleOffCmd && !Config.DEVELOPER.OWNER.includes(interaction.user.id)) { 80 interaction.reply({ 81 ephemeral: true, 82 content: "This command has been disabled by developer!" 83 }); 84 }; 85 86 //===============< MAINTENANCE CMD >===============\\ 87 if (command.maintenanceCmd && !Config.DEVELOPER.OWNER.includes(interaction.user.id)) { 88 interaction.reply({ 89 ephemeral: true, 90 content: "This command has been maintenance by developer!" 91 }); 92 }; 93 94 //===============< COOLDOWN CMD >===============\\ 95 if (onCoolDownInt(interaction, command) && !Config.DEVELOPER.OWNER.includes(interaction.user.id)) { 96 interaction.reply({ 97 ephemeral: true, 98 content: `Please wait \`${onCoolDownInt(interaction, command).toFixed(1)}\` before using the \`${interaction.commandName}\` command again!` 99 });100 };101102 //===============< EXECUTE CMD >===============\\103 try {104 command.execute(client, interaction);105 } catch (error) {106 errorCmdLogsInt(client, interaction, error)107 console.log(`${color.bold.red(`[INTERACTION > CONTEXT: ERROR]`)} ` + `${error}`.bgRed);108 };109 };110 }111};
112
113/**
async
function without any await
expressions23 * @param {Client} client
24 */
25
26 async execute(interaction, client) {27 if (interaction.isButton()) {28 if (interaction.user.bot) return;29 const command = client.buttonCommands.get(interaction.customId);30 if (!command) {31 interaction.reply({32 ephemeral: true,33 content: "Failed to execute button!"34 });35 };363738 //===============< DEVELOPER ONLY >===============\\39 if (command.authorOnly && !interaction.user.id) {40 interaction.reply({41 ephemeral: true,42 content: "This action can only be used by Author!"43 });44 };4546 //===============< EXECUTE CMD >===============\\47 try {48 command.execute(client, interaction);49 } catch (error) {50 errorCmdLogsButton(client, interaction, error)51 console.log(`${color.bold.red(`[INTERACTION > BUTTON: ERROR]`)} ` + `${error}`.bgRed);52 };53 };54 }55};
56
57/**
A function that does not contain any await
expressions should not be async
(except for some edge cases
in TypeScript which are discussed below).
Asynchronous functions in JavaScript behave differently than other functions in two important ways:
Promise
.await
operator inside them.Functions are made async
so that we can use the await
operator inside them.
Consider this example:
async function fetchData(processDataItem) {
const response = await fetch(DATA_URL);
const data = await response.json();
return data.map(processDataItem);
}
Asynchronous functions that don't use await
might be an unintentional result of refactoring.
Note: This issue ignores async generator functions.
Generators yield
rather than return
a value and async
generators might yield all the values of another async generator without ever actually needing to use await
.
In TypeScript, one might feel the need to make a function async
to comply with type signatures defined by an interface.
Ideally, the code should be refactored to get rid of such restrictions, but sometimes that isn't feasible
(For example, when we are implementing an interface defined in a 3rd party library like Next.js).
This situation can easily be circumvented by returning the value with a call to Promise.resolve
:
interface HasAsyncFunc {
getNum: () => Promise<number>
}
// Not recommended:
const o: HasAsyncFunc = {
async getNum() { return 1 }
}
// Recommended:
const o: HasAsyncFunc = {
// We only use `Promise.resolve` to adhere to the type
// of the surrounding object.
getNum() { return Promise.resolve(1) }
}
It is also advised to add a comment near the redundant promise to make the intent clear.
async function fetchData(): string {
// `readFileSync` is a synchronous function that blocks
// the main thread, and thus does not need to be `await`ed
return fs.readFileSync("data.txt", "utf-8");
}
performAction(async () => { console.log("no awaits in here") });
async function fetchDataAsync(): Promise<string> {
return await fs.readFile("data.txt", "utf-8")
}
performAction(async () => { await writeToFile(data) });
// Allow empty functions.
async function no_op() {}