setTimeout与setInterval执行

看下这道题的执行结果如何:

console.log(1);   
setTimeout(function { console.log(2); },100)  
setTimeout(function { console.log(3); },50)  
console.log(4); 

首先我们看一下以下代码打印结果

打印结果是 1、4、3、2,你可能觉得理所应当,那我们再看下下面这个例子

console.log(1);   
setTimeout(function { console.log(2); },0)   
console.log(3);

这次的结果又会是什么呢?

1、3、2,不是1、2、3。到这里你可能会有疑惑了,明明定时器设置的时间为0,而且浏览器解析js是按照从上到下执行的,应该是1、2、3才对啊?

到这里我们要提一下浏览器的线程问题。

与js相关的浏览器线程有三个(注意:js解析是单线程) - js代码执行线程( 主线程 ) - UI渲染线程 - 事件循环线程

其中js代码执行线程与UI渲染线程两者是互斥的,也就是说js代码执行线程运行的时候,UI渲染线程会停止工作,这样做也是为了防止js中的DOM操作会导致两线程冲突;而事件循环线程比较特殊,接下来会根据setTimerout的执行过程进行讲解其作用。

回到上面的第一道题目

console.log(1);   
setTimeout(function { console.log(2); },100)  
setTimeout(function { console.log(3); },50)  
console.log(4); 

执行过程:

  1. js主线程运行,遇到console.log(1),直接运行,在控制台输出结果;

  2. 主线程继续运行,然后遇到第一个setTimeout,接着setTimeout中的回调函数会被放入到一个事件队列中(这里的事件队里可以想象成一个备忘录,里面记录的全是一些需要做而未做的事);

  3. 遇到第二个setTimeout,其中的回调函数依然被加入到事件队列中;

  4. 执行console.log(4),到这里主线程的任务全部执行完毕,除了setTimeout里面的回调函数;

  5. 这个时候,我们还未说明的事件循环线程开始工作,它会去循环遍历事件队列(也就是我们的备忘录),如果事件队列中有回调函数,它就会将事件队列中的回调函数重新交给主线程;

  6. 主线程收到回调函数,然后开始执行函数体。(这里要注意,因为两个setTimeout本身有执行时间,所以在这里的时候就会根据时间的长短按顺序执行啦。)

setInterval原理与之相同,不作另说。

总的来说,setTimeout与setInterval的执行会等到主线程的所有任务全部执行后,才会再执行其中的回调函数,所以在使用它们的时候也要注意,特别是在主线程中有特别耗时的任务的时候,两种定时器会被不可预测的延后。

讲到这里,大家有没有想到什么呢?

恩,就是异步,setTimeout的执行有没有一点异步的感觉呢?但又因为它必须是等到主线程全部执行完才会执行,所以可以称之为伪异步。

说到异步,我们还会想到AJAX,都说AJAX是异步,但是它异步的原理想必还不清楚的你应该有点兴趣了解的。

异步:简单说就是在处理某一件事的时候还可以去做别的事,比如:你在银行取号后等待取钱,在等待的过程中你还可以玩手机,和别人聊天等等,这个过程就是异步的。

AJAX 异步的原理

  1. 发送一个AJAX请求的时候,浏览器会有一个专门的线程来进行该任务;
  2. 而在AJAX中也是有回调函数的,比如请求成功后的回调,失败后的回调,这些回调函数与setTimeout中的回调一样会被推入到事件队列中;
  3. 浏览器接会再次提供一个线程接收AJAX请求返回的数据;
  4. 事件循环线程这时候知道事件队列中AJAX的回调函数能够被执行了,遍历事件队列,将其中的回调函数交回给js主线程;
  5. 主线程执行AJAX回调函数内部代码。

总的说来,AJAX的请求不会干扰到主线程任务的执行,它有自己专供的线程来处理其任务

setTimeout与setInterval到AJAX异步的更多相关文章

  1. 详解使用postMessage解决iframe跨域通信问题

    这篇文章主要介绍了详解使用postMessage解决iframe跨域通信问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  2. iOS:核心图像和多线程应用程序

    我试图以最有效的方式运行一些核心图像过滤器.试图避免内存警告和崩溃,这是我在渲染大图像时得到的.我正在看Apple的核心图像编程指南.关于多线程,它说:“每个线程必须创建自己的CIFilter对象.否则,你的应用程序可能会出现意外行为.”这是什么意思?我实际上是试图在后台线程上运行我的过滤器,所以我可以在主线程上运行HUD(见下文).这在coreImage的上下文中是否有意义?

  3. ios – 多个NSPersistentStoreCoordinator实例可以连接到同一个底层SQLite持久性存储吗?

    我读过的关于在多个线程上使用CoreData的所有内容都讨论了使用共享单个NSPersistentStoreCoordinator的多个NSManagedobjectContext实例.这是理解的,我已经使它在一个应用程序中工作,该应用程序在主线程上使用CoreData来支持UI,并且具有可能需要一段时间才能运行的后台获取操作.问题是NSPersistentStoreCoordinator会对基础

  4. ios – XCode断点应该只挂起当前线程

    我需要调试多线程错误.因此,为了获得生成崩溃的条件,我需要在代码中的特定点停止一个线程,并等待另一个线程到达第二个断点.我现在遇到的问题是,如果一个线程遇到断点,则所有其他线程都被挂起.有没有办法只停止一个线程,让其他线程运行,直到它们到达第二个断点?)其他更有趣的选择:当你点击第一个断点时,你可以进入控制台并写入这应该在该断点处暂停当前上下文中的线程一小时.然后在Xcode中恢复执行.

  5. ios – 在后台线程中写入Realm后,主线程看不到更新的数据

    >清除数据库.>进行API调用以获取新数据.>将从API检索到的数据写入后台线程中的数据库中.>从主线程上的数据库中读取数据并渲染UI.在步骤4中,数据应该是最新数据,但我们没有看到任何数据.解决方法具有runloops的线程上的Realm实例,例如主线程,updatetothelatestversionofthedataintheRealmfile,因为通知被发布到其线程的runloop.在后台

  6. ios – NSURLConnectionLoader线程中的奇怪崩溃

    我们开始看到我们的应用启动时发生的崩溃.我无法重现它,它只发生在少数用户身上.例外情况是:异常类型:EXC_BAD_ACCESS代码:KERN_INVALID_ADDRESS位于0x3250974659崩溃发生在名为com.apple.NSURLConnectionLoader的线程中在调用时–[NSBlockOperationmain]这是该线程的堆栈跟踪:非常感谢任何帮助,以了解可能导致这种崩

  7. ios – 合并子上下文时的NSObjectInaccessbileExceptions

    我尝试手动重现,但失败了.是否有其他可能发生这种情况的情况,是否有处理此类问题的提示?解决方法在创建子上下文时,您可以尝试使用以下行:

  8. ios – 从后台线程调用UIKit时发出警告

    你如何处理项目中的这个问题?

  9. ios – 在SpriteKit中,touchesBegan在与SKScene更新方法相同的线程中运行吗?

    在这里的Apple文档AdvancedSceneProcessing中,它描述了更新方法以及场景的呈现方式,但没有提到何时处理输入.目前尚不清楚它是否与渲染循环位于同一个线程中,或者它是否与它并发.如果我有一个对象,我从SKScene更新方法和touchesBegan方法(在这种情况下是SKSpriteNode)更新,我是否要担心同步对我的对象的两次访问?解决方法所以几天后没有回答我设置了一些实验

  10. ios – 在后台获取中加载UIWebView

    )那么,有一种方法可以在后台加载UIWebView吗?解决方法如果要从用户界面更新元素,则必须在应用程序的主队列(或线程)中访问它们.我建议您在后台继续获取所需的数据,但是当需要更新UIWebView时,请在主线程中进行.你可以这样做:或者您可以创建一个方法来更新UIWebView上的数据,并使用以下方法从后台线程调用它:这将确保您从正确的线程访问UIWebView.希望这可以帮助.

随机推荐

  1. xe-ajax-mock 前端虚拟服务

    最新版本见Github,点击查看历史版本基于XEAjax扩展的Mock虚拟服务插件;对于前后端分离的开发模式,ajax+mock使前端不再依赖后端接口开发效率更高。CDN使用script方式安装,XEAjaxMock会定义为全局变量生产环境请使用xe-ajax-mock.min.js,更小的压缩版本,可以带来更快的速度体验。

  2. vue 使用 xe-ajax

    安装完成后自动挂载在vue实例this.$ajaxCDN安装使用script方式安装,VXEAjax会定义为全局变量生产环境请使用vxe-ajax.min.js,更小的压缩版本,可以带来更快的速度体验。cdnjs获取最新版本点击浏览已发布的所有npm包源码unpkg获取最新版本点击浏览已发布的所有npm包源码AMD安装require.js安装示例ES6Module安装通过Vue.use()来全局安装示例./Home.vue

  3. AJAX POST数据中文乱码解决

    前端使用encodeURI进行编码后台java.net.URLDecoder进行解码编解码工具

  4. Koa2框架利用CORS完成跨域ajax请求

    实现跨域ajax请求的方式有很多,其中一个是利用CORS,而这个方法关键是在服务器端进行配置。本文仅对能够完成正常跨域ajax响应的,最基本的配置进行说明。这样OPTIONS请求就能够通过了。至此为止,相当于仅仅完成了预检,还没发送真正的请求呢。

  5. form提交时,ajax上传文件并更新到<input>中的value字段

  6. ajax的cache作用

    filePath="+escape;},error:{alert;}});解决方案:1.加cache:false2.url加随机数正常代码:网上高人解读:cache的作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取。

  7. 浅谈ajax上传文件属性contentType = false

    默认值为contentType="application/x-www-form-urlencoded".在默认情况下,内容编码类型满足大多数情况。在这里,我们主要谈谈contentType=false.在使用ajax上传文件时:在其中先封装了一个formData对象,然后使用post方法将文件传给服务器。说到这,我们发现在JQueryajax()方法中我们使contentType=false,这不是冲突了吗?这就是因为当我们在form标签中设置了enctype=“multipart/form-data”,

  8. 909422229_ajaxFileUpload上传文件

    ajaxFileUpload.js很多同名的,因为做出来一个很容易。我上github搜AjaxFileUpload出来很多类似js。ajaxFileUpload是一个异步上传文件的jQuery插件传一个不知道什么版本的上来,以后不用到处找了。语法:$.ajaxFileUploadoptions参数说明:1、url上传处理程序地址。2,fileElementId需要上传的文件域的ID,即的ID。3,secureuri是否启用安全提交,默认为false。4,dataType服务器返回的数据类型。6,error

  9. AJAX-Cache:一款好用的Ajax缓存插件

    原文链接AJAX-Cache是什么Ajax是前端开发必不可少的数据获取手段,在频繁的异步请求业务中,我们往往需要利用“缓存”提升界面响应速度,减少网络资源占用。AJAX-Cache是一款jQuery缓存插件,可以为$.ajax()方法扩展缓存功能。

  10. jsf – Ajax update/render在已渲染属性的组件上不起作用

    我试图ajax更新一个有条件渲染的组件。我可以确保#{user}实际上是可用的。这是怎么引起的,我该如何解决呢?必须始终在ajax可以重新呈现之前呈现组件。Ajax正在使用JavaScriptdocument.getElementById()来查找需要更新的组件。但是如果JSF没有将组件放在第一位,那么JavaScript找不到要更新的内容。解决方案是简单地引用总是渲染的父组件。

返回
顶部