【问题标题】:How to make a xmlhttprequest and onload function within another function in JavaScript?如何在 JavaScript 的另一个函数中创建 xmlhttprequest 和 onload 函数?
【发布时间】:2017-01-24 20:43:51
【问题描述】:

我有一个让xmlhttprequest 获取和解析JSON 的脚本。对于从 JSON 获得的每个值,脚本在前一个 JSON 的 forEach 循环中创建另一个 xmlhttprequest,并尝试从从第二个 JSON 获得的数据中附加 HTML。

我的脚本:

var request; 
request = new XMLHttpRequest(); //make request to post-list file
request.open('GET', 'main.json', true); //post-list file is in base folder
request.onload = function () {
    var dat;
    dat = JSON.parse(request.responseText); //parse the post-list json
    dat.forEach(function (data) {
        req = new XMLHttpRequest(); //make new request for post-detail file
        req.open('GET', data.postid + '.json', true); //path to post-detail file is acquired from post-list file
        req.onload = function () {
            info = JSON.parse(req.responseText); //parse the post-detail file
            // function for page contents
            document.getElementsByClassName('main-content')[0].innerHTML += '<div class="post"><h2><a href="/post.html?id=' + info.postid + '">' + info.title + '</a></h2><p>' + info.excerpt + '...</p></div>';
        };
    });
};
request.send();

我的 HTML:

<!DOCTYPE html>
<html>
<head>
    <script src = "js/main.js"></script>
</head>
<body>
    <div class="main-content"></div>
</body>
</html>

我的 main.json:

[
    {
       "postid": "2",
       "author": "John Doe"
    },
    {
        "postid": "1",
        "author": "John Doe"
    }
]

我的1.json:(请求为data.postid.json):

{
  "postid": "1",
  "author": "Jhon Doe",
  "title": "This is the first title.",
  "category": [
      "Music",
      "Lifestyle"
  ],
  "year": "2017",
  "month": "Jan",
  "date": "24",
  "text": "<p>This is post 1 full text.</p><p>This is the second paragraph.</p>",
  "excerpt": ""
}

实现:http://embed.plnkr.co/B9v5OZK7yAQykmRStECA/

我的结果:只执行第二个 onload 之外的命令。我无法检查是否成功解析了第二个 JSON。

如果我能在没有 jQuery 的情况下做到这一点,我会很高兴。

【问题讨论】:

    标签: javascript json xmlhttprequest


    【解决方案1】:

    您忘记在forEach 循环内调用req.send()。如果您不调用它,则永远不会进行 HTTP 调用。

    我还将event 参数添加到两个onload 调用中,并使用event.target.responseText 变量来获取解析的响应

    var request; 
    request = new XMLHttpRequest(); 
    request.open('GET', 'main.json', true); 
    request.onload = function (event) { // <-- Add event argument 
        var dat;
        dat = JSON.parse(event.target.responseText); // <-- and use event.target to get the response text
        dat.forEach(function (data) {
            req = new XMLHttpRequest(); 
            req.open('GET', data.postid + '.json', true);
            req.onload = function (event) { // <-- Add event argument 
                info = JSON.parse(event.target.responseText); // <-- and use event.target to get the response text
                var cat = info.category;
                var catl = cat.length;
                var ti = '';
                for (i = 0; i < catl; i++) {
                    ti += '<a href="category.html?id=' + cat[i].replace(" ", "-") + '">' + cat[i] + '</a>';
                    if (i < catl - 1) {
                        ti += ', ';
                    }
                }
                document.getElementsByClassName('main-content')[0].innerHTML += '<div class="post"><h2><a href="/post.html?id=' + info.postid + '">' + info.title + '</a></h2><p>' + info.excerpt + '...</p><div class="meta"><a href="/author.html?id=' + info.author.replace(" ", "-") + '">' + info.author + '</a> in ' + ti + ' <i class="link-spacer"></i> ' + info.month + ' ' + info.date + ', ' + info.year + ' <i class="link-spacer"></i> <i class="fa fa-bookmark"></i> ' + info.time + ' min read </div></div>';
            };
            req.send(); // <-- You need to send every inner request, otherwise the HTTP call is never made
        });
    };
    request.send();
    

    请在此处查看工作示例:https://plnkr.co/edit/Alewp8nW9aPjlbO0DDi1

    【讨论】:

    • 有趣的是,它似乎返回了两次相同的帖子,而不是 2 个不同的帖子。得进一步诊断。 embed.plnkr.co/qOvlq6MRfu5J4yM1fao5
    • 我更新了 Plunker 代码和上面的响应来解决问题。我使用 onload 函数的 event 参数。如果你的答案没问题,请批准:)
    • 是的,它似乎正在工作。这是批准的答案。
    最近更新 更多