How to properly do a createReactionCollection –
I’ve been wanting to create an event when a user presses a reaction that is a Check or X. Although, when I use the function I get an error that it doesn’t exist for the message object.
I’ve already from awaitReactions back to this and it hasn’t worked.
EDIT:
I did a console.log
to the messageSent object and I got this Promise { <pending> }
var messageSent = user.send({embed})
.then(function (message) {
message.react('✅')
message.react('❎')
});
messageSent.createReactionCollection(r => ['✅','❎'].includes(r.emoji.name))
.on('collect', r => {
if (r.emoji.name == '✅') {
user.send("Verified! ✅")
} else if (r.emoji.name == '❎') {
user.send("Canceled! ❎")
}
});
}
TypeError: messageSent.createReactionCollection is not a function
at app.post (C:UsersteddyDesktopVerifyapp.js:46:25)
at Layer.handle [as handle_request] (C:UsersteddyDesktopVerifynode_modulesexpresslibrouterlayer.js:95:5)
at next (C:UsersteddyDesktopVerifynode_modulesexpresslibrouterroute.js:137:13)
at Route.dispatch (C:UsersteddyDesktopVerifynode_modulesexpresslibrouterroute.js:112:3)
at Layer.handle [as handle_request] (C:UsersteddyDesktopVerifynode_modulesexpresslibrouterlayer.js:95:5)
at C:UsersteddyDesktopVerifynode_modulesexpresslibrouterindex.js:281:22
at Function.process_params (C:UsersteddyDesktopVerifynode_modulesexpresslibrouterindex.js:335:12)
at next (C:UsersteddyDesktopVerifynode_modulesexpresslibrouterindex.js:275:10)
at expressInit (C:UsersteddyDesktopVerifynode_modulesexpresslibmiddlewareinit.js:40:5)
at Layer.handle [as handle_request] (C:UsersteddyDesktopVerifynode_modulesexpresslibrouterlayer.js:95:5)
Solution :
Sync vs Async
Say you’re planning on picking your friend up to go to a sporting event. You’re not sure when they want you to come, so you call them on the phone and ask them. They think about it for a while, and then tell you a time. You got the information you requested, so you hang up. In programming terms, this would be an example of synchronous code (sometimes thought of as “normal” code in Node.js).
Put yourself back in the same situation. However, when you call your friend this time, they’re very busy. You don’t want to bother them so you ask them to call you later. You hang up, but now you wait. An hour later, they call you back and tell you the time. This is the thought process of asynchronous code.
There’s a lot more that goes on behind the screen, but for simplicity’s sake, I’m not going to bombard you with all that information.
Promises
The
Promise
object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Let’s break the code down to better understand the problem.
User.send()
returns a Promise.Promise.then()
also returns a Promise.
Therefore, your code really looks like this:
var messageSent = Promise --> Promise
A
Promise
is in one of these states:
- pending: initial state, neither fulfilled nor rejected.
- fulfilled: meaning that the operation completed successfully.
- rejected: meaning that the operation failed.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
I did a
console.log
to the messageSent object and I got thisPromise { <pending> }
Although you defined the variable as a Promise, it isn’t completed right away, and therefore no value is returned yet. It’s in its pending state.
Solutions
So, how do we retrieve the result of a Promise? We have to wait for it.
-
Keeping a simple flow, you can use the
await
keyword. All it does is wait for the Promise to be fulfilled or rejected before continuing the execution of further code. Consider the following example:// Asynchronous context (meaning within an async function) needed to use 'await.' var messageSent = await user.send(embed); await messageSent.react('✅'); await messageSent.react('❎'); // Create reaction collector.
-
Alternatively, you could stick to
then()
chains. The callback will be called with the returned value upon the fulfillment of the Promise. In some contexts, this is simple. However, callbacks can get messy very quickly, and the scope of the returned values will be limited. Consider this example:user.send(embed) .then(messageSent => { messageSent.react('✅') .then(() => messageSent.react('❎')) .then(() => { // Create reaction collector. }); }); // Keep in mind that the code here will be executed immediately after 'user.send(embed).'
-
I might have fixed it, for some reason it wasn’t returning the object of the message so I added
messageSent = message;
to the .thenThis works in your case because the value in the
then()
callback will be the fulfilled Promise, and you’re setting the variable to the returned value. This isn’t the best idea, though.
Error Handling
When a Promise is rejected, it means something went wrong. Errors originating from rejected Promises must be caught. If they aren’t, you’ll receive a warning in the console with the error.
-
You can attach
catch()
methods which will work similarly tothen()
, except returning the error as its callback parameter and only being called upon rejection. Consider this short example:user.send(embed) .then(messageSent => {...}) .catch(console.error);
-
Instead of attaching multiple
catch()
methods, you can use atry...catch
statement. If any Promises inside of thetry
block are rejected, the code inside thecatch
block is executed. For example:try { const user = await bot.fetchUser('someID'); await user.send(embed); } catch(err) { console.error(err); }