0

我是 JavaScript 新手,我正在 Github 页面上为 Discord 机器人运行 wiki,当我尝试使用预制 JSON 文件中的代码更新页面时,它必须运行两次才能正常运行,它目前在这里,我使用控制台运行该功能。当我运行该addCommands();函数时,它返回 undefined 并且一开始什么也不做,但是当我第二次运行它时,它可以工作

命令.js

var commands_json;

function addCommands() {
  $(function () {
    $.getJSON("./commands.json", function (data) {
      commands_json = data.Commands;
    });
    for (var command in commands_json) {
      console.log(command);
      command_div = document.getElementById("commands");
      command_div.innerHTML +=
        "<div class=" +
        command +
        ' id="command"><h1>' +
        command +
        "</h1><h2>" +
        commands_json[command]["desc"] +
        "</h2><h3>Known Errors: " +
        commands_json[command]["errs"] +
        "</h3></div>";
      if (commands_json[command].subcommands != undefined) {
        for (var subcommand in commands_json[command]["subcommands"]) {
          document.getElementsByClassName(command)[0].innerHTML +=
            "<h4>" +
            subcommand +
            "</h4><h5>" +
            commands_json[command]["subcommands"][subcommand]["desc"] +
            "</h5><h6>Known Errors:" +
            commands_json[command]["subcommands"][subcommand]["errs"] +
            "</h6>";
        }
      }
    }
  });
}

命令.json

{
  "Commands": {
    "$decrypt": {
      "desc": "Decrypts a given message with the given key",
      "errs": "There is no error handling to stop it from creating an error if the key fails to decrypt the message"
    },
    "$encrypt": {
      "desc": "Encrypts a message with the given key",
      "errs": "None known"
    },
    "$generatekey": {
      "desc": "Generates an encryption key for encrypting messages",
      "errs": "None known"
    },
    "$eval": {
      "desc": "Evaluates a given expression",
      "errs": "Very strict notation, doesn't accept most symbols such as 2^2 not resulting in 4, while 2**2 results in 4"
    },
    "$meme": {
      "desc": "Using the PRAW library, this command receives the newest post from r/memes",
      "errs": "If the poster deletes their post, only the image is deleted, and the post still remains, therefore it returns an empty embed"
    },
    "$dankmeme": {
      "desc": "Using the PRAW library, this command receives the newest post from r/memes",
      "errs": "Same error as the $memes command"
    },
    "$inventory": {
      "desc": "Opens the user data JSON file and creates an embedding of the items in the user's inventory",
      "errs": "None known"
    },
    "$reset": {
      "desc": "Completely erases the user's account from the user data JSON file",
      "errs": "None known"
    },
    "$shutdown": {
      "desc": "Intended for shutting down the bot while notifying people who are on the \"notifiy\" list",
      "errs": "None known"
    },
    "$ping": {
      "desc": "Returns the bot's responsiveness in seconds, aka ping",
      "errs": "None known"
    },
    "$twitter": {
      "desc": "Part of a list of sub commands that receives tweets from Twitter using Tweepy",
      "errs": "None Known",
      "subcommands": {
        "$twitter trending": {
          "desc": "Takes the WOE (Where On Earth) ID and produces a list of tweets that are trending in that area",
          "errs": "No exception handling for when the WOE ID is incorrect"
        },
        "$twitter user": {
          "desc": "Takes a Twitter username and gets tweets from that person's account",
          "errs": "None known"
        },
        "$twitter hashtags": {
          "desc": "Takes a hashtag and searches any usages of the hashtag",
          "errs": "None known"
        }
      }
    },
    "$reddit": {
      "desc": "Part of a list of sub commands that receives a list of posts from Reddit from the subreddit using PRAW",
      "errs": "None known",
      "subcommands": {
        "$reddit subreddit": {
          "desc": "Takes posts from a subreddit using PRAW",
          "errs": "None known"
        }
      }
    },
    "$pypi": {
      "desc": "Scrapes https://www.pypi.org/ for a packages info",
      "errs": "None known"
    },
    "$status": {
      "desc": "Shows the statuses of the bot and the Discord API",
      "errs": "None known"
    }
  }
}

4

3 回答 3

1

您的异步函数有问题getJSON。您必须将所有代码放在回调中。

function addCommands() {
    $(function () {
        $.getJSON("./commands.json", function (data) {
            var commands_json = data.Commands;

            for (var command in commands_json) {
                console.log(command);
                command_div = document.getElementById("commands");
                command_div.innerHTML +=
                    "<div class=" +
                    command +
                    ' id="command"><h1>' +
                    command +
                    "</h1><h2>" +
                    commands_json[command]["desc"] +
                    "</h2><h3>Known Errors: " +
                    commands_json[command]["errs"] +
                    "</h3></div>";
                if (commands_json[command].subcommands != undefined) {
                    for (var subcommand in commands_json[command]["subcommands"]) {
                        document.getElementsByClassName(command)[0].innerHTML +=
                            "<h4>" +
                            subcommand +
                            "</h4><h5>" +
                            commands_json[command]["subcommands"][subcommand]["desc"] +
                            "</h5><h6>Known Errors:" +
                            commands_json[command]["subcommands"][subcommand]["errs"] +
                            "</h6>";
                    }
                }
            }
        });
    });
}

现在发生的事情如下:

  • commands_json 已声明并具有值undefined.
  • addCommands运行 jquery 等待 dom 准备好,然后执行你的函数。
  • 您异步调用 getJSON。这意味着for它开始执行之后的权利在 getJSON 结束之前。
  • for 执行,但由于 getJSON 尚未完成,commands_json 仍然未定义并且它会中断。
  • getJSON完成并将结果保存在 commands_json
  • addCommands第二次跑
  • getJSON再次异步调用
  • 在完成for之前开始运行,getJSON但这次commands_json保存了第一次调用的结果。
  • 这次for循环按预期工作
  • 完成getJSON并保存结果后,commands_json此值将被忽略,因为使用它的代码已经执行
于 2020-07-04T02:31:57.840 回答
1

问题是 $.getJSON 是一个异步 AJAX 调用。它不会立即返回。它发出调用,并在它完成时调用 funcion(data) 并设置 commands_json。在调用之后和返回之前,它将继续执行其余的代码,因此 for 循环将在 $.getJSON 返回之前运行,并且变量 commands_json 尚未设置。但它会在不久之后返回。这就是为什么当你第二次调用它时它起作用的原因,因为到那时 $.getJSON 已经返回了。那么解决方案是什么?只需将整个代码放入函数(数据)中即可。因为那样代码将在返回时运行。像这样:

var commands_json;

function addCommands() {
    $(function() {
        $.getJSON("./commands.json", function(data) {
            commands_json = data.Commands;
            for (var command in commands_json) {
                console.log(command);
                command_div = document.getElementById("commands");
                command_div.innerHTML +=
                    "<div class=" +
                    command +
                    ' id="command"><h1>' +
                    command +
                    "</h1><h2>" +
                    commands_json[command]["desc"] +
                    "</h2><h3>Known Errors: " +
                    commands_json[command]["errs"] +
                    "</h3></div>";
                if (commands_json[command].subcommands != undefined) {
                    for (var subcommand in commands_json[command]["subcommands"]) {
                        document.getElementsByClassName(command)[0].innerHTML +=
                            "<h4>" +
                            subcommand +
                            "</h4><h5>" +
                            commands_json[command]["subcommands"][subcommand]["desc"] +
                            "</h5><h6>Known Errors:" +
                            commands_json[command]["subcommands"][subcommand]["errs"] +
                            "</h6>";
                    }
                }
            }
        });

    });
}
于 2020-07-04T02:34:53.830 回答
-2

确保在页面准备好时调用函数,请参阅示例代码。

document.addEventListener('DOMContentLoaded', function(){ 
    // Call function or write your code here
}, false);
于 2020-07-04T02:27:07.290 回答