单线程特点执行异步操作

  js是单线程语言,浏览器只分配给js一个主线程,用来执行任务(函数),但一次只能执行一个任务,这些任务就会排队形成一个任务队列排队等候执行.一般而已,相对耗时的操作是要通过异步来进行加载,可以避免导致页面的假死.
setTimeout(function(){
console.log(这是timeout事件回调);
},1000);
  JS阻塞renderdom的渲染,同一时间只能做一件事,避免了浏览器渲染DOM冲突,JS执行的时候,JS可以修改DOM,浏览器DOM渲染会停止,WebWorker支持多线程,但不能渲染DOM.

解决方案——异步

setTimeout(function(){
console.log(这是timeout事件回调);
},1000);
  执行这段代码的时候,浏览器异步执行计时操作,传入setTimeout的函数会被暂存起来,当1000ms到了后,会触发定时事件,这个时候,就会把回调函数放到任务队列里,待所有程序执行完,处于空闲的状态时,会立马看看有没有暂存起来要执行的任务,整个程序就是通过这样的一个个事件驱动起来的,如下图1.1所示:
图1.1 工作原理图

  "任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等),例如onClick事件,只要指定这些事件的异步操作,就会进入任务队列中等待执行.
  其中JS实现异步是不断通过事件轮询(Event Loop)的方式实现的,同步代码直接执行,异步代码先放在异步队列中,等待同步代码执行完,轮询执行异步队列中的异步代码
  AJAX请求天气接口数据如下:
<script type="application/javascript" src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script type="application/javascript">
function urlencode (str) {
str = (str + '').toString();
return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').
replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+');
}
var city= '深圳',$citycode=urlencode(city);
var url='http://v.juhe.cn/weather/index?format=2&cityname='+$citycode+'&key=c82727e986a4f6cfc6ba1984f1f9183a';
$.ajax({url: url,
dataType: "jsonp",
type:"get",
data:{location:city},
success:function(data) {
var sk = data.result.sk;
var today = data.result.today;
var futur = data.result.future;
var fut = "日期温度天气风向";
$('#mufeng').html(
"<p>" + '当前: ' + sk.temp + '℃ , ' + sk.wind_direction + sk.wind_strength +
' , ' + '空气湿度' + sk.humidity + ' , 更新时间' + sk.time +
"</p><p style='padding-bottom: 10px;'>" + today.city + ' 今天是: ' + today.date_y +
' ' + today.week + ' , ' + today.temperature + ' , ' + today.weather + ' , ' + today.wind + "<p></p>"
);
}}); </script>

结果如下所示:先打印cc1,cc222, 然后执行25行success中代码

问题

  1. Callback没有按照我们预期的顺序执行
  2. Callback不易于我们进行模块化管理

jQuery.Deferred

jQuery1.5的变化,语法糖改变,遵循开发封闭原则

$.ajax({url: url,
dataType: "jsonp",
type:"get",
data:{location:city}})
.done(function(data){
if(data.result){
var sk = data.result.sk;
var today = data.result.today;
var futur = data.result.future;
var fut = "日期温度天气风向";
$('#mufeng').html(
"<p>" + '当前: ' + sk.temp + '℃ , ' + sk.wind_direction + sk.wind_strength +
' , ' + '空气湿度' + sk.humidity + ' , 更新时间' + sk.time +
"</p><p style='padding-bottom: 10px;'>" + today.city + ' 今天是: ' + today.date_y +
' ' + today.week + ' , ' + today.temperature + ' , ' + today.weather + ' , ' + today.wind + "<p></p>"
);
}else {
console.log('该接口调用达到上限')
}
})
.fail(function(){
console.log("获取数据失败")
})
.done(function(data){
console.log(data)
})

Deferred的另一种写法:

$.ajax({url: url,
dataType: "jsonp",
type:"get",
data:{location:city}})
.then(function(data){
if(data.result){
var sk = data.result.sk;
var today = data.result.today;
var futur = data.result.future;
var fut = "日期温度天气风向";
$('#mufeng').html(
"<p>" + '当前: ' + sk.temp + '℃ , ' + sk.wind_direction + sk.wind_strength +
' , ' + '空气湿度' + sk.humidity + ' , 更新时间' + sk.time +
"</p><p style='padding-bottom: 10px;'>" + today.city + ' 今天是: ' + today.date_y +
' ' + today.week + ' , ' + today.temperature + ' , ' + today.weather + ' , ' + today.wind + "<p></p>"
);
}else {
console.log('该接口调用达到上限')
}
},function(){
console.log("获取数据失败1")
})
.then(function(data){
console.log(data);
},function(){
console.log("获取数据失败2")
})

执行结果如下图所示:

$.Defferred 对象封装 返回一个defferred对象

    function waitHandleWeather() {
var dtd = $.Deferred()
var wait =function(dtd){
$.ajax({url: url,
dataType: "jsonp",
type:"get",
data:{location:city}})
.then(function(data){
dtd.resolve(data)
},function(){
dtd.reject('该接口调用达到上限') //返回promise对象,如果返回dtd,外面就可以修改dtd的操作,不安全
});
return dtd.promise();
}
return wait(dtd); //返回promise对象
}
var weatherDataDeferred = waitHandleWeather();
$.when(weatherDataDeferred).then(function(data){
if(data.result){
var sk = data.result.sk;
var today = data.result.today;
var futur = data.result.future;
var fut = "日期温度天气风向";
$('#mufeng').html(
"<p>" + '当前: ' + sk.temp + '℃ , ' + sk.wind_direction + sk.wind_strength +
' , ' + '空气湿度' + sk.humidity + ' , 更新时间' + sk.time +
"</p><p style='padding-bottom: 10px;'>" + today.city + ' 今天是: ' + today.date_y +
' ' + today.week + ' , ' + today.temperature + ' , ' + today.weather + ' , ' + today.wind + "<p></p>"
);
}else {
console.log('该接口调用达到上限')
}
},function(err){
console.log(err)
});

同步和异步的区别

  同步在执行的过程会阻塞I/O,在正常的流程中执行的顺序不同,例如setTimeout、setInterval,会改变流程执行的顺序,尽管setTimeout的time延迟时间为0,其中的function也会被放入一个队列中,等待下一个机会执行,当前的代码(指不需要加入队列中的程序)必须在该队列的程序完成之前完成,因此结果可能不与预期结果相同。因此,异步能改变流程执行的顺序,同步不会改变流程执行的顺序,依次执行.
 

jQuery.Deferred和Promise 区别

Promise不能主动干预改变promise的结果,Deffrred可以去改变干预执行的结果

最后,如果想看promise相关内容,请移步https://www.cnblogs.com/fuGuy/p/9215884.html

浅谈JS异步轮询和单线程机制的更多相关文章

  1. 浅谈js异步

    大家都知道,js是一个单线程的语言(只有一个线程来执行js函数),所以如果某一个函数执行任务耗时比较长的话,就会造成阻塞,使得后续任务一直处于等待状态. 一.阻塞示例 function f1(){ ; ...

  2. 浅谈JS异步(asychrouous)

    一.概念 (1)asychronous 异步 是JS这种单线程语言解决多任务的一种方法,将耗时的任务(io)设定为异步工作,先交给浏览器负责相关功能的线程来实现耗时的部分工作,按顺序放入任务队列中,等 ...

  3. 浅谈.Net异步编程的前世今生----APM篇

    前言 在.Net程序开发过程中,我们经常会遇到如下场景: 编写WinForm程序客户端,需要查询数据库获取数据,于是我们根据需求写好了代码后,点击查询,发现界面卡死,无法响应.经过调试,发现查询数据库 ...

  4. 浅谈JS之AJAX

    0x00:什么是Ajax? Ajax是Asynchronous Javascript And Xml 的缩写(异步javascript及xml),Ajax是使用javascript在浏览器后台操作HT ...

  5. 浅谈JS中的闭包

    浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...

  6. 浅谈 js 正则字面量 与 new RegExp 执行效率

    原文:浅谈 js 正则字面量 与 new RegExp 执行效率 前几天谈了正则匹配 js 字符串的问题:<js 正则学习小记之匹配字符串> 和 <js 正则学习小记之匹配字符串优化 ...

  7. 浅谈 js 字符串之神奇的转义

    原文:浅谈 js 字符串之神奇的转义 字符串在js里是非常常用的,但是你真的了解它么?翻阅<MDN String>就可以了解它的常见用法了,开门见山的就让你了解了字符串是怎么回事. 'st ...

  8. 浅谈 js 正则之 test 方法

    原文:浅谈 js 正则之 test 方法 其实我很少用这个,所以之前一直没注意这个问题,自从落叶那厮写了个变态的测试我才去看了下这东西.先来看个东西吧. var re = /\d/; console. ...

  9. 浅谈 js 数字格式类型

    原文:浅谈 js 数字格式类型 很多人也许只知道 ,123.456,0xff 之类的数字格式.其实 js 格式还有很多数字格式类型,比如 1., .1 这样的,也有 .1e2 这样的. 可能有人说这是 ...

随机推荐

  1. Python实现冒泡,选择排序

    def bubble(num): for i in range(len(num)-1): for j in range(len(num)-i-1): if(num[j]>num[j+1]): t ...

  2. winform基础控件-例子学习

    1.如图实现整数计算器 ComboBox控件: Items属性:添加集合中的项. this.comoper.Items.AddRange(new object[] { "+", & ...

  3. python的enumerate函数

    python的enumerate函数用于循环索引和元素 例如 foo = 'abc' for i , ch in enumerate(foo): print ch, '(%d)' % i 输出结果: ...

  4. sql语句 查询分组后的每组的第一条或最后一条数据

    select * from(select row_number() over(partition by IDCARD order by DATATM desc) as rownum,* from (S ...

  5. cmd命令提示符大全(干货)

    cmd是command的缩写.即命令提示符(CMD),是在OS / 2 , Windows CE与Windows NT平台为基础的操作系统(包括Windows 2000和XP中, Vista中,和Se ...

  6. php给图片加文字

    在图片上加文字是论坛,博客,新闻网站上最喜欢用的功能,防止盗图.这里看看代码是如何实现的. 首先还是upload_image.php这个文件,注意这里的caption文本框中输入的内容最终会写到图片上 ...

  7. Programming Assignment 3: Baseball Elimination

    编程作业三 作业链接:Baseball Elimination & Checklist 我的代码:BaseballElimination.java 问题简介 这是一个最大流模型的实际应用问题: ...

  8. 使用Visual Studio Code编写和激活ABAP代码 (上)

    猪年春节后的第一篇,Jerry祝各位猪年大吉! 2019年的六分之一马上就快过完了,不知道大家在新的一年是否给自己定了新的小目标呢?这里Jerry先预祝大家到2019年年底的时候,在年初制定的小目标都 ...

  9. DZ拿shell总结

    今天碰到一个dz的站,好久没拿了 ,拿下shell觉得应该总结一下 Uc_server默认密码 其实有了UC_SERVER就是有了网站的全部权限了,有了UC_SERVER你可以重置管理员密码 可以进后 ...

  10. IOS 了解新技术(UIPresentationController,屏幕适配)

    1.了解有什么新技术1> 苹果API文档 - General - Guides - iOSx API Diffs2> 观看WWDC会议视频 2.如何使用新技术 1> 自己根据API文 ...