Ajax同步导致浏览器出现假死现象

在前端点击按钮,向后端请求数据,在后端计算的过程中,前端会有一个响应界面,我们一般会用一个“正在加载...”的效果。

在Ajax中,有两种请求方式,即异步和同步,默认是异步请求。

在异步请求的时候,向后端请求数据,和当前js页面后面的程序执行是异步的。

而同步执行的时候,后面的js程序,要等到后端数据返回之后,才能继续执行下去。

如果采用同步执行的方式,会导致动态小效果的加载,看不到“正在加载...”的效果。

所以可以采用异步的方式代替。

主要采用jQuery中的Deferred对象,以及其中的一些方法。

详细的原理可以参见:https://javascript.ruanyifeng.com/jquery/deferred.html或者https://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html(阮一峰  )

这里摘抄一些原理性的东西,方便记忆:

1. deferred对象代表了将要完成的某种操作(“延迟”的意思),并提供了一些方法。它是jQuery对Promises接口的实现。jQuery的所有Ajax操作函数,默认返回的就是一个deferred对象

2. Promises是异步操作的通用接口,扮演代理人(proxy)的角色,将异步操作包装成具有同步操作特性的特殊对象。异步操作的典型例子就是Ajax操作、网页动画、web worker等等。

3. 由于JavaScript单线程的特点,如果某个操作耗时很长,其他操作就必需排队等待。为了避免整个程序失去响应,通常的解决方法是将那些排在后面的操作,写成“回调函数”(callback)的形式。这样做虽然可以解决问题,但是有一些显著缺点:

> 回调函数往往写成函数参数的形式,形成所谓的“持续传递风格”(即参数就是下一步操作,Continuation-passing style),导致函数的输入和输出非常混乱,整个程序的可阅读性差;

> 回调函数往往只能指定一个,如果有多个操作,就需要改写回调函数。

> 除了正常的报错机制,错误还可能通过回调函数的形式返回,增加了除错和调试的难度。

> 正常的函数输入和输出可以区分得很清楚,回调函数使得函数的输出不再重要。

Promises就是为了解决这些问题而提出的,它的主要目的就是取代回调函数,成为非同步操作的解决方案。它的核心思想就是让非同步操作返回一个对象,其他操作都针对这个对象来完成。比如,假定ajax操作返回一个Promise对象。

有关Promises对象的使用,可以参见上面的网站。

这里解决问题,主要采用的是Deferred对象将Ajax返回的数据进行封装。在主线程中,采用回调函数的方式,进一步处理返回的数据,以及线程中下面的程序。

具体使用如下:

//主线程
$('.btn').click(function() {
  //这里使用layui框架实现动态效果
  document.querySelector('.chartes').showLoading({
    text: '正在加载数据...'
  });
  $.when(getData()).done(function(data) { 
    document.querySelector('.chartes').hideLoading();
    alert(data);
  });
});

//被调用的Ajax方法
function getData() { 
   var defer = $.Deferred(); //初始化一个Deferred对象
   $.ajax({ 
   url : '',
   async : true, // true异步。false同步
   success : function(data) { 
       defer.resolve(data); //resolve表示已完成状态
     } 
  }); 
  //promise()方法表示在原来的deferred对象上返回另一个deferred对象,
  //后者只开放与改变执行状态无关的方法(比如done()方法和fail()方法),屏蔽与改变执行状态有关的方法(比如resolve()方法和reject()方法),
  //从而使得执行状态不能被改变。
  return defer.promise();
 }

所以,以上是通过Deferred对象的链式操作得以解决,学习了...

特别注意的是:以上用法只能在jQuery版本高于1.5.0的版本中,因为低于1.5.0,返回的是XHR对象,无法进行链式操作, 而Deferred对象可以进行链式操作。

Deferred对象的链式操作详见阮一峰老师的博客:https://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html

原文地址:https://www.cnblogs.com/Archie2018/p/13755554.html