如何使用 2 个 XMLHttpRequest 一个依赖于另一个

How to work with 2 XMLHttpRequest one dependent on another?

本文关键字:一个 依赖于 另一个 何使用 XMLHttpRequest      更新时间:2023-09-26

我正在做一个项目,我有 2 个 XMLHttpRequest() 对象,比如 A 和 B。

我想完成的是,当 A 完成获取数据项列表时,将触发 B 根据 A 先前获取的数据项获取更多项目。

目前我的问题是这两个对象彼此独立工作。

我的代码如下:

            var A = new XMLHttpRequest();
            var B = new XMLHttpRequest();
            A.open("GET", directory, true);
            A.onreadystatechange = function () {
                if (A.readyState === 4) {
                    if (A.status === 200 || A.status == 0) {
                     //does... something
                     }
                }
            }
            A.send(null);
            while(true){
                B.open("GET", another_directory, false);
                B.overrideMimeType("application/document");
                B.send(null);
                if (B.status == "404")
                continue;
                 //does... something else
            }

这段代码不起作用,因为我发现每次 B 在 A 完成之前继续。我基本上不知道要使用哪个事件。

如何实现我的目标?我可以使用哪些事件,以便在完成 A 后立即同步处理 B?

好的,让我们从你的代码开始。我在其中添加了一些注释,因此现在您可以了解问题的根源:

var A = new XMLHttpRequest(); //You create an XMLHttpRequest object
var B = new XMLHttpRequest(); //And an another
A.open("GET", directory, true); 
/* Now you open a GET request to DIRECTORY, with async TRUE. The third parameter can 
make a request sync or async, but sync is not recommended as described below. */
A.onreadystatechange = function () {
    if (A.readyState === 4) {
        if (A.status === 200 || A.status == 0) {
        /* So you registered an event listener. It runs when the readyState changes.
        You can use it to detect if the request is finished or not. If the readyState is
        4, then the request is finished, if the status code is 200, then the response is
        OK. Here you can do everythin you want after the request. */
         }
    }
}
A.send(null); //Now you send the request. When it finishes, the event handler will
// do the processing, but the execution won't stop here, it immediately goes to the 
// next function
while(true){ // Infinite loop
     B.open("GET", another_directory, false); //Open request B to ANOTHER_DIRECTORY,
     // but now, request B will be synchronous
     B.overrideMimeType("application/document"); // Configure mime type
     B.send(null); // Send the request
     if (B.status == "404")
         continue;
         // If it's not found, then go to the next iteration
     // and do something else
}

我希望现在你能看到问题的根源。运行此脚本时,将启动异步请求,然后立即启动下一个请求。现在您可以从 2 种方式中进行选择。

从回调运行下一个请求(推荐)

这是更好的方法。因此,启动第一个(异步)请求,在事件侦听器(执行处理的位置)中,您可以启动下一个请求。我在这里做了一个注释的例子:http://jsfiddle.net/5pt6j1mo/1/

(你可以在没有数组的情况下做到这一点 - 这只是一个例子)

如果您使用这种方式,则在您等待响应之前,GUI 不会冻结。一切都将负责,因此您可以与页面交互,您可以创建取消按钮等。

同步 AJAX(不推荐)

我不推荐它,因为Chrome中的"主线程上的同步XMLHttpRequest已被弃用",但是如果您真的想要,则可以尝试使用此解决方案。因此,XMLHttpRequest 的 open 函数有 3 个参数:

  • 方法:使用哪个 HTTP 甲基
  • 网址
  • :要请求的网址
  • 异步
  • :异步请求?如果为 false,那么它将是同步的,这意味着在你调用 .send() 之后,它将暂停执行,直到响应返回。

因此,如果您将第三个参数设置为 FALSE,那么您可以轻松做到......但你不应该!

这是一个替代解决方案,要么使用获取 API 或承诺本机 XHR,这个问题变得更加简单:

fetch(directory).then(function(response){
    // some processing
    return fetch(another_directory); // can change content type too, see the mdn docs
}).then(function(responseTwo){
      // all processing is done
}).catch(function(err){
      // handle errors from all the steps above at once
});

这与 XHR 一样原生,并且使用承诺进行管理要简单得多。

(经过长时间的编辑)我强烈建议您花时间了解JavaScript中异步调用的本质。这里有一些推荐阅读。JavaScript 中的异步编程我认为这很简单,可以理解正在发生的事情。 注意:在"输入Mobl"处停止阅读。

在 JavaScript 中,当你调用一个函数时,系统会将该函数放入一个"队列"中,并带有一个隐式指令,以继续并尽快运行它。 它对每个函数调用都这样做。 在您的情况下,您告诉系统运行 A,然后运行 B。 A 进入队列,B 进入队列。 它们作为单独的函数提交。 B 碰巧先运行。

对于普通函数,如果要控制序列,可以将 A 函数调用嵌套在 B 函数调用中。 但是哎呀。您正在使用 XMLHttpRequest,因此限制了您自定义函数的能力。 请继续阅读。 查看有关该主题的 Ajax 模式 查看"异步调用"段落。 看看你的代码...

A.onreadystatechange = function () {
    if (A.readyState === 4) {
         if (A.status === 200 || A.status == 0) {
             //does... something
             (RUN ALL THE B.methods right here...)
         }
    }
}

我认为这会让你到达目的地,假设你想要一个没有jQuery的解决方案。

对于那些只想要一个正常运行的系统,并且不想更好地理解语言的人来说,这里有一个jquery解决方案......请注意 B 函数调用是如何嵌套在 A 函数调用中的。 请注意,此嵌套的顺序基于jQuery成功标记的存在。 如果不使用 jQuery,则必须根据需要手动嵌套函数。

var special_value;
$("button").click(function(){
    $.ajax({url: "demo_testA.html", 
            type: 'GET',
            success: function(resultA){
               special_value = resultA;
               $.ajax({url: "demo_testB.html",
                      type: 'GET', 
                      data: special_value, 
                      success: function(resultB){
                            $("#div1").html(resultB);
               }});
    });
});

我会说,帮助您使用更好的通信会容易得多。 如果你不喜欢某件事,那就说出来。 如果您不理解某些内容,请要求进一步澄清或编辑您的问题陈述。 反馈是一件好事。