【问题标题】:how to run javascript while waiting for the ajax callback如何在等待ajax回调时运行javascript
【发布时间】:2012-11-17 01:18:50
【问题描述】:

我正在对服务器进行 ajax 调用。我需要运行的代码可以分为3组。

  1. 需要在 ajax 调用之前运行的代码(准备 json 对象到服务器)
  2. 需要在 ajax 调用返回后运行的代码(使用从服务器发回的内容)
  3. 需要在用户按下按钮和一切完成之间运行的代码。此代码不需要返回的 json 对象。

在进行 ajax 调用之后和结果返回之前运行第 3 组中的代码以获得最佳用户体验和性能是理想的。

这个可以吗?

怎么做?

【问题讨论】:

标签: javascript ajax json jquery


【解决方案1】:

很简单:

function someFunction() {
    //1. code that needs to run before ajax
    $.ajax({...}).done(function () {
        //2. code that needs to be run after the ajax call has returned
    });
    //3. code that needs to be run between the time the user presses
    //   a button and the time everything is done.
}

之所以可行,是因为 JavaScript 在执行中是同步的(除非正在使用工作人员,但这与这个特定问题无关)。第一段代码会运行,然后ajax调用会告诉浏览器启动一个XHR请求,但是someFunction还没有完成,所以会继续同步执行。

一旦someFunction 完成,控制流将对发生的任何异步事件开放,最终导致done 回调。

公平地说,异步面向事件的编程对于大多数人来说并不容易理解。很容易忘记应该在什么时间发生什么代码。

这是一个易于执行的异步行为如何工作的示例:

(function () {
    alert(1);
    setTimeout(function () {
        alert(2);
    }, 0); //note the 0ms delay
    alert(3);
}());

警报的顺序为132setTimeout 不会同步调用它的回调,因为它依赖于等待指定的时间过去,所以即使没有时间过去,它仍然必须等待当前函数完成才能继续。

【讨论】:

  • +1 - 这是许多开发人员难以理解的内容。
  • //3 真的保证在//2 之前运行吗?假设//3 包含许多需要很长时间才能计算/完成的函数,理论上//2 在执行//3 中的任何内容期间的任何时候都不能跳入调用堆栈吗?我不是说异步调用,我只是在想,由于//2 是事件驱动的,因此事件可能会在执行中的任何给定点触发。
  • @Jan,异步事件的“触发”只是将函数调用添加到执行流queue。只有在先前排队的函数完全完成执行后,队列才会移动到下一个函数调用。除非函数调用明确使用多线程(例如与工作线程),否则无法混合函数调用。
【解决方案2】:

在响应客户端事件或在任何其他情况下执行 ajax 调用允许您在回调中指定代码以及在 ajax 代码生成后立即执行的代码(而不是在回调中)。

例子:

// Code before the ajax call is made
$.ajax({
    params, //other key values such as data
    success: function (data) {
       // one of the possible callbacks
    }
});
// Code executed immediately after ajax call is performed
// This is executed before or after the callback is complete
// In most cases it's before

因此,在进行 ajax 调用之前执行的任何操作都可以保证在之前执行。几乎可以保证在调用 ajax 之后立即执行任何操作,然后再调用回调。回调保证在服务器返回响应后执行。

【讨论】:

  • “这是在回调完成之前或之后执行的”,我打算对此投反对票,因为回调不能在完成之前发生,但后来我记得如果有同步回调是可能的它被用作一个选项。我不确定我是否喜欢你的措辞,因为它暗示异步回调可能在控制流被释放之前发生,但它不会。
  • @zzzzBov 您还可以在异步代码之后添加异步代码。所以不能保证在第一次回调之前执行。这就是我的回答是这样的原因。如果您认为可以改进我的答案,请随时编辑:)
  • 异步代码(如setTimeout(fn, delay))的调用将在任何异步回调发生之前执行。函数执行后,任何排队的函数都将按照它们被调用的顺序执行。例如,success 回调可能会使用缓存数据,并立即将其回调排队,但仍保证在当前执行的函数完成后发生。
  • @zzzzBov 同意。仍然 js 是同步的,所以有些情况下回调在代码之后执行之前执行,所以我必须准确地说“之前或之后”,否则我会错的 :)
猜你喜欢
  • 2011-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-29
  • 1970-01-01
  • 2016-09-03
相关资源
最近更新 更多