How to properly do a createReactionCollection

Posted on

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 this Promise { <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 .then

    This 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 to then(), 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 a try...catch statement. If any Promises inside of the try block are rejected, the code inside the catch block is executed. For example:

    try {
      const user = await bot.fetchUser('someID');
      await user.send(embed);
    } catch(err) {
      console.error(err);
    }
    

Resources

Leave a Reply

Your email address will not be published. Required fields are marked *