JavaScript Discord bot array iteration issue with async callbacks

I’m building a Discord bot in JavaScript and running into a weird problem with array iteration. When I try to loop through an array and make API calls, the loop variable seems to get messed up inside the callback function.

Here’s my code:

const Discord = require('discord.js');
const fetch = require('node-fetch');
const TOKEN = "your_bot_token";
const API_KEY = "?key=your_api_key";
const STREAM_API = "https://api.example.com/status/";
const client = new Discord.Client();
var streamers = ["streamer_a", "streamer_b", "streamer_c"];

client.login('bot_token_here');

client.on("message", function(msg) {
    if (msg.content === "!status") {
        for (var j = 0; j < streamers.length; j++) {
            fetch(STREAM_API + streamers[j] + API_KEY)
                .then(response => response.json())
                .then(data => {
                    if (data.online == false) {
                        msg.reply(streamers[j] + ' is offline');
                    } else {
                        msg.reply(streamers[j] + ' is online');
                    }
                });
        }
    }
});

The strange thing is that when I log the loop counter before the API call, it shows 0, 1, 2 correctly. But inside the callback function, it always shows 3. This makes the bot display “undefined is online/offline” instead of the actual streamer names. The loop itself works fine, but something happens with the variable inside the async callback. Anyone know what’s causing this behavior?

The problem is that var has function scope, not block scope. When the fetch promises resolve, the loop’s already finished and j equals 3 - so all closures reference the same variable. Switch to let instead since it creates a new binding each iteration. You could also use forEach directly on the streamers array or wrap your fetch in an IIFE to capture the current value. I prefer forEach because it’s more readable.

Had this exact same issue with my first Discord bot. It’s JavaScript’s event loop timing - your for loop finishes instantly while the fetch requests are still running. When those promises finally resolve, the loop variable j has already hit 3, so you’re getting undefined since streamers[3] doesn’t exist. Don’t rely on the loop variable - pass the streamer name directly into your promise chain. Try fetch(STREAM_API + streamers[j] + API_KEY).then(response => response.json()).then(data => { /* use streamers[j] here becomes the actual streamer name */ }) or even better, use streamers.forEach(streamer => { fetch(STREAM_API + streamer + API_KEY)... }) to skip the closure problem completely.

classic closure problem! the loop finishes before your promises resolve, so j hits 3 (out of bounds). use let instead of var in your for loop - it creates block scope for each iteration. that’ll fix the undefined issue ur seeing.