Home > Enterprise >  How can I stop a loop from completing once it gets the first returned object from an API?
How can I stop a loop from completing once it gets the first returned object from an API?

Time:03-30

The code below receives all of the user's redeemed rewards from an API, I need to stop the loop from completing them all at once.

The for loop runs through all of the rewards the current user has redeemed through Twitch's API, then fulfills them if specific conditions are met. I want it to only fulfill one redemption, not all (x) amount of them.

The fulfill reward part happens at: fulfillReward()

For a full code snippet, click here: https://pastebin.com/7k5WNhmD

        // looping over reward returned data
    for (let i = 0; i < rewards.length; i  ) {
      async function fulfillReward() {
        await fetch(
          `https://api.twitch.tv/helix/channel_points/custom_rewards/redemptions?broadcaster_id=58606718&reward_id=08d5e2d9-ddd7-4082-bc78-39b06b35cd68&id=${rewards[i].id}`,
          {
            method: 'PATCH',
            headers: {
              'client-Id': process.env.TWITCHBOT_CLIENT_ID,
              Authorization: `Bearer ${process.env.TWITCHBOT_ACCESS_TOKEN}`,
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({
              status: 'FULFILLED',
            }),
          }
        )
      }

      const currentReward = rewards[i]
      const currentRewardUsername = currentReward.user_name.toLowerCase()

      if (currentRewardUsername === input.toLowerCase()) {
        countDocuments(discordID)
          .then(() => {
            return findOneUser(discordID)
          })
          .then(() => {
            // All (x) amount of rewards get fulfilled instead of the first matching result 
            fulfillReward()
            interaction.reply('success')
          })
          .catch((err) => console.log(err))
      } else if (currentRewardUsername != input.toLowerCase()) {
        return interaction.reply(`The Twitch user **${input}** has not redeemed the channel reward!`)
      }
    }

CodePudding user response:

The general solution to exit a loop when a condition is met, is to incorporate a break statement in whatever conditional decides the loop has achieved its purpose early.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break

I've made a simple snippet that runs a million cycle for-next loop but terminates after 10 loops when a condition is met, using break.

let loopNumber = 0;

for (let i=0; i<1000000; i  )
  {
    loopNumber  ;
    
    if (loopNumber==10) {
    break;
    }
    
  } // next i;
  
  console.log(loopNumber);

CodePudding user response:

Not sure I understood completely what you actually want but lets try:

   async function fulfillReward(reward) {
      await fetch(
        `https://api.twitch.tv/helix/channel_points/custom_rewards/redemptions?broadcaster_id=58606718&reward_id=08d5e2d9-ddd7-4082-bc78-39b06b35cd68&id=${reward.id}`,
        {
          method: 'PATCH',
          headers: {
            'client-Id': process.env.TWITCHBOT_CLIENT_ID,
            Authorization: `Bearer ${process.env.TWITCHBOT_ACCESS_TOKEN}`,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            status: 'FULFILLED',
          }),
        }
      )     
    }

If you just receive the reward as a parameter you don't need to declare functions inside the for (please don't ever do that)

Then you call it sending the reward parameter

 if (currentRewardUsername === input.toLowerCase()) {
        countDocuments(discordID)
          .then(() => {
            return findOneUser(discordID)
          })
          .then(() => {
            fulfillReward(currentReward)
            interaction.reply('success')
          })
          .catch((err) => console.log(err))
      } else if (currentRewardUsername != input.toLowerCase()) {
        return interaction.reply(`The Twitch user **${input}** has not redeemed the channel reward!`)
      }

I updated your code here https://pastebin.com/clone/7k5WNhmD, but cant really test it, so please let me know if you need something else

CodePudding user response:

try this.

for (let i = 0; i < rewards.length; i  ) {
      async function fulfillReward() {
        await fetch(
          `https://api.twitch.tv/helix/channel_points/custom_rewards/redemptions?broadcaster_id=58606718&reward_id=08d5e2d9-ddd7-4082-bc78-39b06b35cd68&id=${rewards[i].id}`,
          {
            method: 'PATCH',
            headers: {
              'client-Id': process.env.TWITCHBOT_CLIENT_ID,
              Authorization: `Bearer ${process.env.TWITCHBOT_ACCESS_TOKEN}`,
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({
              status: 'FULFILLED',
            }),
          }
        )
      }

      const currentReward = rewards[i]
      const currentRewardUsername = currentReward.user_name.toLowerCase()
      

      if (currentRewardUsername === input.toLowerCase()) {
         function doSomething() {
              return new Promise((resolve, reject) => {
                 countDocuments(discordID)
                  .then(() => {
                    return findOneUser(discordID)
                  })
                  .then(() => {
                    // All (x) amount of rewards get fulfilled instead of the first matching result 
                    fulfillReward()
                    interaction.reply('success')
                    resolve(true);
                  })
                  .catch((err) => console.log(err))
            })
         }
          
         const ret = await doSomething();
 
         if (ret)
            return ;
            
      } else if (currentRewardUsername != input.toLowerCase()) {
        return interaction.reply(`The Twitch user **${input}** has not redeemed the channel reward!`)
      }
    }
  • Related