Jquery ajax 同步阻塞引起的UI线程阻塞的坑(loading图片显示不出来 )

Jquery ajax 同步阻塞引起的UI线程阻塞的坑(loading图片显示不出来,layer.load延迟)jax重新获取数据刷新页面功能,因为ajax属于耗时操作,想在获取数据且加载页面时显示加载遮罩层,结果发现了ajax的好多坑。

Jquery ajax 同步阻塞引起的UI线程阻塞的坑(loading图片显示不出来,layer.load延迟)

ajax请示时,让遮罩层显示,ajax加载完毕后遮罩层消失。

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

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

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

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

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

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

那么需要使用到: 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.mzph.cn/news/164629.shtml

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

相关文章

Elasticsearch自动清理脚本

脚本 我在data下创建的脚本文件就叫:vi /data/clear_log.sh,内容如下 #!/bin/sh #获取时间 time=`date +%Y-%m-%d %H:%M:%S` cipan=`df -h| grep sda3` #查询磁盘使用率 liang=`df -h| grep sda3 |grep -v grep |awk {print $5}|tr -d

【数据结构】一题带你出师链表!

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 题目链接 138. 随机链表的复制https://leetcode.cn/problems/copy-list-with-random-pointer/ 题目描述 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机…

Make a BESD file from QTLtools output

Make a BESD file from QTLtools output # 根据基因名与变异rsid编号去重 library(tidyverse) library(readxl) qtltoolsnomi <- read_table("qtltoolsnomi.txt",col_names F) qtltoolsnomi %>% distinct(X1,X8, .keep_all TRUE) -> qtltool qtltool …

qml ParticleSystem3D使用介绍

在 Qt Quick 3D 中,ParticleSystem3D 是用来创建和控制3D粒子系统的元素。粒子系统是图形编程中用于模拟液体、烟雾、火、星空等现象的技术,它通过生成大量小粒子来模拟这些效果。ParticleSystem3D 提供了一个框架,允许开发者定义粒子的各种属性,如生命周期、速度、颜色、大…

王道p149 9.设树B是一棵采用链式结构存储的二叉树,编写一个把树 B中所有结点的左、右子树进行交换的函数。(c语言代码实现)

本题代码如下 void swap(tree* t) {if (*t){treenode* temp (*t)->lchild;(*t)->lchild (*t)->rchild;(*t)->rchild temp;swap(&(*t)->lchild);swap(&(*t)->rchild);} } 完整测试代码 #include<stdio.h> #include<stdlib.h> typed…

C#string.Format的一些使用

C#中的string.Format方法是一个用于格式化字符串的功能强大的方法。它允许您通过将占位符替换为实际的值来创建格式化的字符串。 一、基本语法是&#xff1a; string.Format(format, arg0, arg1, arg2, ...) 其中&#xff0c; format是一个字符串&#xff0c;其中包含要格式…

Java常用类

目录 包装类 装箱和拆箱 包装类型和String的转换&#xff0c;包装类的常用方法 包装类 装箱和拆箱 package com.edu.wrapper;public class Interger01 {//演示int<-->Integer的装箱和拆箱//手动装箱int n1100;Integer integer new Integer(n1);Integer integer01 In…

HCIP---MPLS---LDP

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 MPLS 基于标签转发表进行转发&#xff0c;与路由表类似&#xff0c;标签转发表有两种获取渠道&#xff1a;一是手动配置(类似静态路由)&#xff0c;二是通过协议自动学习(类似OSPF)。手动配…

6.1.webrc媒体协商

那今天呢&#xff1f;我们来看一下y8 rtc的媒体协商&#xff0c;那实际上在我们之前的课程中呢&#xff1f;我已经向你介绍过y8 rtc的媒体协商了。只不过呢&#xff0c;角度是不一样的&#xff0c;在之前介绍外边tc媒体协商的时候呢&#xff0c;我们是从应用的角度来看。那web …

ActiveMQ消息中间件应用场景

一、ActiveMQ简介 ActiveMQ是Apache出品&#xff0c;最流行的&#xff0c;能力强劲的开源消息总线。ActiveMQ是一个完全支持JMS1.1和J2EE1.4规范的JMS Provide实现。尽管JMS规范出台已经是很久的事情了&#xff0c;但是JMS在当今的J2EE应用中仍然扮演这特殊的地位。 二、Active…

《第一行代码:Android》第三版-2.5.4数据类与单例_数据类

本文主要讲述数据类&#xff0c;以前用java实现数据类很麻烦&#xff0c;写很多代码&#xff0c;就是搭个数据类的框架。kotlin用data class 关键字&#xff0c;给你简化了数据类的创建&#xff0c;比较贴心。 就是自动为你创建了&#xff1a;equals()、hashCode()、toString(…

深入理解JVM 类加载机制

深入理解JVM 类加载机制 虚拟机如何加载Class文件&#xff1f; Class文件中的信息进入到虚拟机后会发生什么变化&#xff1f; 类加载机制就是Java虚拟机把描述类的数据从Class文件加载到内存&#xff0c;并对数据进行校验、转换解析和初始化&#xff0c;最终形成可以被虚拟机…

实现点击一个选框 使得一个组件的可选性修改

实现效果 代码 html <div class"divrow"><el-checkbox-group v-model"isSendTag" :max"1"><el-checkbox v-for"(item, index) in isSendTagOptions" :key"index" :label"item.value">{{item.…

【C++设计模式】单例模式singleton

C 设计模式–单例模式singleton 单例模式 单例模式是指确保一个类在任何情况下都绝对只有一个实例&#xff0c;并提供一个全局访问点。 优点&#xff1a;内存中只有一个实例&#xff0c;减少内存开销&#xff1b;避免对资源多重占用&#xff1b;设置全局访问点&#xff0c;严…

【Axure教程】用中继器制作卡片多条件搜索效果

卡片设计通过提供清晰的信息结构、可视化吸引力、易扩展性和强大的交互性&#xff0c;为用户界面设计带来了许多优势&#xff0c;使得用户能够更轻松地浏览、理解和互动。 那今天就教大家如何用中继器制作卡片的模板&#xff0c;以及完成多条件搜索的效果&#xff0c;我们会以…

并发与并行

并发和并行是操作系统中的两个重要概念&#xff0c;它们在定义和处理任务的方式上有一些区别。 并发&#xff08;concurrency&#xff09;是指在一段时间内&#xff0c;有多个程序都处于启动运行到运行完毕之间&#xff0c;但任一时刻点上只有一个程序在处理机上运行。它是一种…

Vue侦听器

Vue侦听器是根据组件状态做DOM更新或者异步更新其他级联状态的。计算属性的主要目标是根据已有数据计算出组件的状态&#xff0c;它是组件内部的计算&#xff0c;计算结果在组件内部应用。侦听器的主要目标是根据组件状态的变动&#xff0c;做级联的或者异步的操作或DOM更新&am…

STM32F103C8T6第6天:adc、iic、spi、温湿度dht11在lcd1602显示

1. ADC介绍 ADC是什么&#xff1f; Analog-to-Digital Converter&#xff0c;指模拟/数字转换器 ADC的性能指标 量程&#xff1a;能测量的电压范围分辨率&#xff1a;ADC能辨别的最小模拟量&#xff0c;通常以输出二进制数的位数表示&#xff0c;比如&#xff1a;8、10、1…

【Spring篇】Spring注解式开发

本文根据哔哩哔哩课程内容结合自己自学所得&#xff0c;用于自己复习&#xff0c;如有错误欢迎指正&#xff1b; 我在想用一句话激励我自己努力学习&#xff0c;却想不出来什么惊为天人、精妙绝伦的句子&#xff0c;脑子里全是上课老师想说却没想起的四个字 “ 唯手熟尔 ”&am…

自动驾驶术语汇总

目录 智驾级别芯片相关自动驾驶相关辅助驾驶相关预警相关传感器相关泊车相关安全相关车灯相关 智驾级别 L0-L2属于辅助驾驶&#xff0c;L4-L5才算自动驾驶 L0&#xff08;Level 0&#xff09;&#xff1a;无自动化。这是大多数传统汽车的级别&#xff0c;所有的驾驶任务都需要…