Javascript 我应该为我的ajax调用实现故障保护,还是不需要?

Javascript 我应该为我的ajax调用实现故障保护,还是不需要?,javascript,jquery,ajax,Javascript,Jquery,Ajax,如果我没有记错的话,javascript是单线程的,这意味着在同一时间只做一件事。我正在创建一个完整的ajax网页,通过向服务器发送数据,并在javascript的帮助下在屏幕上呈现结果,完成所有导航 让我们以以下javascript为例: $.post( "script.php", function( data ) { for (var z=0; z<data; z++) { console.log("B"); } }); $.post( "script.php", f

如果我没有记错的话,javascript是单线程的,这意味着在同一时间只做一件事。我正在创建一个完整的ajax网页,通过向服务器发送数据,并在javascript的帮助下在屏幕上呈现结果,完成所有导航

让我们以以下javascript为例:

$.post( "script.php", function( data ) {
  for (var z=0; z<data; z++) {
    console.log("B");
  }
});

$.post( "script.php", function( data ) {
  for (var z=0; z<data; z++) {
    console.log("C");
  }
});

var i=-1;
while (i<0) { 
/* I know that this is an infinite cycle, but let's just bear with this for the sake of my 
example, and let's pressume the browser would run this correctly, without lagging, crashing*/
  console.log("A");
}
$.post(“script.php”,函数(数据){

对于(var z=0;z而言,它们完全可能以错误的顺序到达。阻止UI以触发第二个ajax调用,或者在第二个调用开始之前杀死第一个调用(如果第一个调用没有返回)

联网是一件痛苦的事情,如果你打开chrome开发工具,你会发现每个请求的启动和停止都会伴随着传输时间的随机波动。有时第一个字节的时间会因为一些奇怪的原因而爆炸。网络很奇怪

即使加载此页面,也会有先启动后完成的请求。如果用户触发了ajax调用,则需要处理它们。如果您以编程方式执行一系列ajax调用,则有一些库可以简化这一过程


你的提问方式有点混乱,这可能解释了一些针对其他问题的冗长回答,但没有一个回答了你想要的。你问题的关键(从你对其他答案的后续评论中可以看出)是关于用户点击内容链接并让内容以错误的顺序显示。最糟糕的情况是,一个较早的请求在一个较晚的请求之后完成,并覆盖屏幕上的内容

虽然可以在当前请求完成之前停止接收新请求(阻塞),但这违反了异步方法的目的

理想情况下,人们会跟踪请求,并在出现新的请求时取消它们,新的请求应取代以前的请求

下面是一个简化方法的示例,该方法使用别名
$.ajax
,以便为现有请求添加跟踪

/*
 * Declare a function that will be used to load content and track previous requests
 *
 * Notice we're not assigning it to the function that is being defined on the same line,
 * ather that function is executing immeidately and its return value, a function, will
 * be assigned.
 */
var loadContent = (function () {
    // Privatized variable which will hold the last made request
    var last_request;

    /*
     * The actual definition of loadContent (notice it is being returned)
     * Takes a URL and options (just like $.ajax). it looks to see if there was a previous request and whether it has finished.
     * If there is a prev request, and it hasn't finished, it is aborted.
     *
     * @param string url Where to make the request
     * @param object opts optional $.ajax options
     */
    return function (url, opts) {
        // Look for previous request. If there is one, and it isn't finished, abort it
        if (last_request && last_request.ready_state !== 4) {
            last_request.abort();
        }

        // Make the new request, storing it into our tracked last request
        last_request = $.ajax(url, opts || {});

        // Return the (new) last request for use outside use of promises, etc if desired
        return last_request;
    };
}());
通过此函数发出的任何请求都将取消以前通过它发出的任何请求。请注意,您仍然可以同时使用
$.ajax
或其他别名。您将通过此函数路由所有ajax调用,这将导致以前发出的类似调用中止,同时对
$.ajax 在与需要替代的特定功能不相关的代码的其他区域中

下面是我所说的最后一部分的示例:

鉴于此HTML:

<div>
    <ul>
        <li><a href="/aboutus.html" class="content-link">About</a></li>
        <li><a href="/services.html" class="content-link">Services</a></li>
    </ul>

    <div id="content">
        Main Site Content
    </div>

    <div id="feedContent">
        Perhaps something loading dynamically from a feed
    </div>
</div>
你问:

当一个jQuery帖子完成时会发生什么?由于javascripts的单线程性,while循环的执行是否停止,脚本是否开始执行该帖子的回调

但在示例代码中,您声明:

我知道这是一个无限的循环,但为了我的利益,让我们忍耐一下吧 例如,让我们按一下,浏览器将正确运行,不会出现延迟和崩溃

这种说法使我们无法回答这个问题

如果允许我们不做这样的假设,并且允许我们准确地解释在真正的浏览器中发生了什么,那么我们就可以回答这个问题

下面是:

当一个jQuery帖子完成时会发生什么? 它永远不会结束

这是因为浏览器永远不会发送网络数据包

这是因为while循环正在运行

这是为什么?这与事件循环的工作方式有关。下面是事件循环的简单示意图:

事件循环
┌──────────┐
│          │
│          │
│          ▼
│        (1) 看看有没有新的───────▶ 解析数据
│        网络上的数据│
│          │                                        │
│          ▼                                        │
│        (2) 检查我们是否需要执行◀─────────┘
│        任何javascript─────────────────────▶ 执行
│          │                                  javascript
│          ▼                                        │
│        (3) 看看我们是否需要◀──────────────────┘
│        重新绘制页面──────────────────▶ 重画页面
│          │                                        │
│          │                                        │
└────◀─────┴─────────────────◀──────────────────────┘
您的
while
循环导致浏览器陷入步骤(2)——执行javascript

jqueryajax函数不会向服务器发送ajax请求,它只是在浏览器的网络代码中对ajax请求进行排队

浏览器在执行javascript时无法执行任何其他操作。它无法绘制到屏幕,无法发送网络数据包。这是因为它是单线程的

一旦不再运行javascript(一旦程序结束),浏览器最终将重新进入事件循环,并可以执行图形和网络代码

当浏览器返回到步骤(1)时,它最终将两个ajax请求发送到服务器。然后很长一段时间内(至少从CPU的角度来看)什么都没有发生。在此期间,浏览器根本不使用您的CPU。如果您查看process manager,您会发现CPU使用率几乎为零

在此期间,由于浏览器不忙,它能够处理用户事件,如鼠标移动和鼠标单击。事件循环不会一直循环。当确实无事可做时,事件循环会在步骤(1)中暂停,等待任何I/O

当服务器的数据包最终到达
$(function () {
    var content_area = $('#content'),
        feed_area = $('#feedContent'),
        // Our previously defined function, minus all the comments
        loadContent = (function () {
            var last_request;

            return function (url, opts) {
                if (last_request && last_request.ready_state !== 4) {
                    last_request.abort();
                }

                last_request = $.ajax(url, opts || {});

                return last_request;
            };
        }());

    // Route main content links through the loadContent method which aborts previous, unfinished requests
    $('a.content-link').on('click', function (e) {
        e.preventDefault();

        loadContent($(this).attr('href'), {
            success: function (content) {
                content_area.html(content);
            }
        });
    });

    // Directly use $.ajax to load something unrelated
    $.ajax('/feed-url', {
        success: function (content) {
            feed_area.html(content);
        }
    });
});