Jquery ajax 进行网络请求,同步阻塞引起的UI线程阻塞 (loading图片不显示 )

jax重新获取数据刷新页面功能,因为ajax属于耗时操作,想在获取数据且加载页面时显示加载遮罩层,结果发现了ajax的好多坑。

ajax 执行http网络请示时时,让遮罩层显示,ajax加载完毕后遮罩层消失。

因为我想让loadChart()在赋值操作后执行,但如果async设为true时,往往会先执行loadChart(),之后才会赋值,

所以我只能将ajax设为同步。但同步后无论我怎么点按钮,遮罩层都不会出来。

解决方法 1:

这时:只有:async:true , loading mask层才会出来

 原因就是ajax的async设置为true时,ajax会委托浏览器另起一个线程,此线程与js线程和ui线程不冲突,只是在执行完成后再插入js事件环。

而ajax的async设置为false时并没有启动单独的线程,还是在js主线程中执行,所以会与浏览器的渲染(UI)线程和js线程是互斥的,在执行js耗时操作时,页面渲染会被阻塞掉。

当我们执行异步ajax的时候没有问题,但当设置为同步请求时,其他的动作(ajax函数后面的代码,还有渲染线程)都会停止下来。即使我的DOM操作语句是在发起请求的前一句,这个同步请求也会“迅速”将UI线程阻塞,不给它执行的时间。这就是代码失效的原因。 

解决方法 2:

那么需要使用到: deferred对象。

 总之,想让ajax走完再加载页面,就要使用同步。但是只要同步,ajax就会阻塞ui线程,使得loading显示不出来。

只有使用了deffer对象和$.when(),既可以ajax设为异步,保证了loading的正常显示,又可以保证在ajax走完再加载页面。因为$.when().done()会在deffer.resolve()之前的代码全部走完后才走done中的代码。

我改成这样。由于ajax为同步时点击切换比较卡。能用异步最好还是用异步,用defferred对象后就可以把async换成true了。$.when()函数只接受defferred对象,所以我们在toGetData中需要先创建对象,再return就解决了。defer.resolve(ret)用于控制ajax何时结束,比如我执行完赋值操作结束ajax,进入.done()中的回调函数,它还可以把数据ret也带出来使用,这里我没有用到,这里执行完loadChart()操作后遮罩层消失。所以它能保证deffer.resolve之前的代码执行完再执行回到函数,async设为true也没任何影响。

     这样就完美解决了因为ajax阻塞线程导致loading层出不来的问题啦。

<script>
    var data;
    function toGetData() {
        var defer = $.Deferred();
        $.ajax({
            url: 'xxx', 
            type: "post", // 请求类型
            data: {
            }, 
            dataType: 'json', 
            async: true, // 是否异步
            success: function (ret) {
                if (ret) {
                    data=ret;
                    defer.resolve(ret)
 
                } else {
                    alert("无数据");
                }
            } 
        });
        return defer;
    }
    $('button').click(function(){
        $(".shadow").show()
        $.when(toGetData()).done(function(ret){
            loadChart()
            $(".shodow").hide()   //所有的ajax的逻辑可以在这个地方进行处理
        });
    })
</script>

什么是deferred对象?

开发网站的过程中,我们经常遇到某些耗时很长的javascript操作。其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是立即能得到结果的。

通常的做法是,为它们指定回调函数(callback)。即事先规定,一旦它们运行结束,应该调用哪些函数。

但是,在回调函数方面,jQuery的功能非常弱。为了改变这一点,jQuery开发团队就设计了deferred对象。

简单说,deferred对象就是jQuery的回调函数解决方案。在英语中,defer的意思是"延迟",所以deferred对象的含义就是"延迟"到未来某个点再执行。

它解决了如何处理耗时操作的问题,对那些操作提供了更好的控制,以及统一的编程接口。它的主要功能,可以归结为四点。下面我们通过示例代码,一步步来学习。

 $.ajax({

    url: "test.html",

    success: function(){
      alert("哈哈,成功了!");
    },

    error:function(){
      alert("出错啦!");
    }

  });

ajax操作的链式写法 

 $.ajax("test.html")

  .done(function(){ alert("哈哈,成功了!"); })

  .fail(function(){ alert("出错啦!"); });

指定同一操作的多个回调函数 

 $.ajax("test.html")

  .done(function(){ alert("哈哈,成功了!");} )

  .fail(function(){ alert("出错啦!"); } )

  .done(function(){ alert("第二个回调函数!");} );

 多个操作指定回调函数

$.when($.ajax("test1.html"), $.ajax("test2.html"))

  .done(function(){ alert("哈哈,成功了!"); })

  .fail(function(){ alert("出错啦!"); });

普通操作的回调函数接口 

var wait = function(){

    var tasks = function(){

      alert("执行完毕!");

    };

    setTimeout(tasks,5000);

  };

普通回调函数需要改造:

var dtd = $.Deferred(); // 新建一个deferred对象

  var wait = function(dtd){

    var tasks = function(){

      alert("执行完毕!");

      dtd.resolve(); // 改变deferred对象的执行状态

    };

    setTimeout(tasks,5000);

    return dtd;

  };

$.when(wait())

  .done(function(){ alert("哈哈,成功了!"); })

  .fail(function(){ alert("出错啦!"); });

上面这种写法,还是有问题。那就是dtd是一个全局对象,所以它的执行状态可以从外部改变。

参考:

jQuery的deferred对象详解 - 阮一峰的网络日志

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/216289.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

集「才华」与「美貌」于一身的原型设计利器—摹客RP

文章目录 画原型做设计&#xff0c;用摹客RP就够了 初遇摹客再遇摹客RP摹客RP简介与注册摹客RP的突出亮点1️⃣拥有海量矢量图标&#xff0c;满足各种设计场景2️⃣打造高扩展性组件&#xff0c;打破传统组件编辑模式3️⃣海量摹客RP模板例子随意挑选4️⃣实现多人实时协同&…

laravel8安装多应用多模块(笔记三)

先安装laravel8 Laravel 安装&#xff08;笔记一&#xff09;-CSDN博客 一、进入项目根目录安装 laravel-modules composer require nwidart/laravel-modules 二、 大于laravel5需配置provider&#xff0c;自动生成配置文件 php artisan vendor:publish --provider"Nwid…

软件设计中如何画各类图之二深入解析数据流图(DFD):系统设计与分析的关键视觉工具

目录 1 前言2 数据流图&#xff08;DFD&#xff09;的重要性3 数据流图的符号说明4 清晰的数据流图步骤4.1 确定系统边界4.2 识别数据流4.3 定义处理过程4.4 确认数据存储4.5 建立数据流动的连线4.6 细化和优化 5 数据流图的用途6 使用场景7 实际应用场景举例8 结语 1 前言 当…

手动创建映像及在OpenStack云计算平台的镜像应用

目录 一、下载 rhel7.6 安装ISO 二、在VMware 的虚拟机内创建虚拟机 三、更改一些设置 1、使用httpd暴露&#xff08;在外部虚拟机&#xff09; 2、添加软件仓库 3、 安装 ACPI 服务 4、使用 cloud-init 获取公钥 5、安装 cloud-utils-growpart 以允许调整分区大小 6、…

【Spring Boot 源码学习】自定义 Banner 信息打印

Spring Boot 源码学习系列 自定义 Banner 信息打印 引言往期内容主要内容1. ResourceBanner 打印1.1 添加默认的 banner.txt 资源文件1.2 指定任意路径的资源文件1.3 添加自定义的信息 2. ImageBanner 打印2.1 添加默认的图像资源文件2.2 指定任意路径的图像资源文件2.3 添加自…

idea自动切换输入法Smart Input

idea搜索后下载 红色表示中文输入法 再ideavim场景下会自动切换成英文非常好用强烈推荐下载一个

Kafka 集群如何实现数据同步

Kafka 介绍 Kafka 是一个高吞吐的分布式消息系统&#xff0c;不但像传统消息队列&#xff08;RaabitMQ、RocketMQ等&#xff09;那样能够【异步处理、流量消峰、服务解耦】 还能够把消息持久化到磁盘上&#xff0c;用于批量消费。除此之外由于 Kafka 被设计成分布式系统&…

Nginx模块开发之http handler实现流量统计(2)

文章目录 一、概述二、Nginx handler模块开发2.1、代码实现2.2、编写config文件2.3、编译模块到Nginx源码中2.4、修改conf文件2.5、执行效果 总结 一、概述 上一篇【Nginx模块开发之http handler实现流量统计&#xff08;1&#xff09;】使用数组在单进程实现了IP的流量统计&a…

【【linux C 编程记述 之 VIM的用法讲述】】

linux C 编程记述 之 VIM的用法讲述 我们所说的编写代码包括两部分&#xff1a;代码编写和编译&#xff0c;在Windows下可以使用Visual Studio来完成这两部&#xff0c;可以在 Visual Studio 下编写代码然后直接点击编译就可以了。但是在 Linux 下这两部分是分开的&#xff0c…

深度学习+不良身体姿势检测+警报系统+代码+部署(姿态识别矫正系统)

正确的身体姿势是一个人整体健康的关键。然而&#xff0c;保持正确的身体姿势可能很困难&#xff0c;因为我们经常忘记这一点。这篇博文将引导您完成为此构建解决方案所需的步骤。最近&#xff0c;我们在使用 POSE 进行身体姿势检测方面玩得很开心。它就像一个魅力&#xff01;…

jenkins + gitlab 自动部署(webhook)

Jenkins是一个流行的开源CI/CD工具&#xff0c;可以与Git等版本控制系统集成&#xff0c;实现自动构建、测试和部署。Webhook是一种机制&#xff0c;可以在Git仓库中设置&#xff0c;在代码提交或合并请求时触发Jenkins构建任务&#xff0c;以完成自动化部署。 实操 设备信息 …

Matplotlib自定义坐标刻度_Python数据分析与可视化

自定义坐标刻度 主次要刻度隐藏刻度与标签花哨的刻度格式格式生成器与定位器 虽然matplotlib默认的坐标轴定位器与格式生成器可以满足大部分需求&#xff0c;但是并非对每一幅图都合适。 主次要刻度 学习前最好有对matplotlib图形的对象层级较为了解&#xff0c;例如查看前面…