JavaScript中的时间是通过定时器控制的,他们分别是window.setInterval和window.setTimeout,我们当然可以省略window,直接使用方法名称调用。

一  事件分类

  在讲解定时器之前,我们需要先明白 JavaScript 中事件(任务)的分类。

  JavaScript 把所有代码当做事件或任务来执行,由于 JavaScript 是单线程的,所以无论如何它都只能自上而下,一个一个的来执行任务,在做一件事时,不能干其他事,即同步。然而,随着时代的发展,异步的需求越来越多,浏览器(宿主环境)就为我们实现了异步执行任务的 API,本文即将要讲解的定时器就是典型的异步操作。

   ECMAScript 是同步执行的,浏览器又实现了异步API,那么 JavaScript 是怎么保证他们不冲突的呢?事件分类解决了这个问题。

  普通的 JavaScript 语句依然同步执行,但他们执行的地方在 JavaScript 主线程执行栈中,这些任务我们称作同步任务。

  异步API 任务则在单独的线程任务队列中执行,这些任务我们称为异步任务。

  这些任务在执行时保持主线程优先原则,即使异步任务满足不用等待立即执行的条件,也还是要等待同步任务执行完毕。

二  setTimeout

  在等待指定的毫秒数后执行函数,语法如下:

  setTimeout(code/function, milliseconds, param1, param2, ...)

  方法接受2个或多个参数,第一个是一段JS代码或一个函数引用,第二个是需要等待的时间(以毫秒计),如果第一个参数是函数引用,并且需要传递参数,可以在后面依次传入。方法返回一个唯一id,代表该定时器,使用clearTimeout(id)可以清除定时器。

  1. setTimeout(functon(){
  2. console.log(new Date());
  3. },3000);
  4. console.log(new Date());
  5. //立即显示一次当前时间,3秒后又将显示一次

  经测试发现:如果第一个参数是一段JS代码而非函数引用,该代码将立即被执行,而不会延时等待。

三    setInterval

  等同于 setTimeout(),但持续重复执行该函数。语法如下:

  setInterval(code/function, milliseconds, param1, param2, ...)

  使用方法和setTimeout()相同。

  1. function timer(){
  2. var d = new Date();
  3. document.body.innerText = d;
  4. }
  5. setInterval(timer,1000);

  上面是一个简单的定时器示例。

  另外,setInterval方法有一个严重的缺陷,那就是不能确保执行时间的准确性。

在执行setInterval()时,假如我们设置每1s执行一次函数,但函数执行一次需要花费2s。浏览器会每隔1s就向一个事件队列中添加一个事件(即执行一次函数),当第一次执行完毕(3s之后了),这时队列中已经有2个事件正在排队了,于是浏览器立即执行第二个事件(等待队列中的第一个)。这样明显和我们本意每1s执行一次函数不符。所以在setInterval中,与其说第二个参数是延时时间,不如说是每个事件执行的最大间隔时间更为准确。因为当事件执行时间大于设置的间隔时间时,两个任务执行之间是没有间隔时间的。

  有些书上表示,到了设置的时间点,如果上一次的函数还没执行完,那么本次事件将不会被添加到事件队列中去,这次事件将被跳过,直到未来设置的某一时间点,前面的任务已经完成,才向队列中添加下一个事件。但浏览器实际上是按照第一种方式管理事件队列的,即到了时间不管前面的是否执行完毕,都插入一个进去,然后依次等待执行。(我用的Chrome  76.0.3869.100测试)

  setInterval主要应用在绘制动画效果上,鉴于它对时间的不准确性,要想获得完美的动画效果请使用CSS3的Animation实现。另外,如果确实需要使用,请务必把握好间隔时间的设置。下面是使用setInterval封装的一个运动函数:

  1. var timer;
  2. function startMove(obj,json,Fn){
  3. var key;
  4. clearInterval(timer);
  5. timer = setInterval(function(){
  6. for(var prop in json){//json是一个包含需要改变的属性和目标值的对象。
  7. var bridge;
  8. if(prop == 'opacity'){
  9. bridge = getStyle(obj,prop)*100;//为了便于计算,先放大100倍
  10. }else{
  11. bridge = parseInt(getStyle(obj,prop));
  12. }
  13. var speed = (json[prop] - bridge)/6;
  14. speed = speed > 0?Math.ceil(speed):Math.floor(speed);//这里为了获得更好的动画效果,动态设置了运动速度。你当然可以给一个常数作为运动速度
  15. if(prop == 'opacity'){
  16. obj.style[prop] = (bridge + speed) / 100;
  17. }else{
  18. obj.style[prop]= bridge + speed + 'px';
  19. }
  20. if(bridge != json[prop]){
  21. key = false;
  22. }else{
  23. key = true;
  24. }
  25. if(key){
  26. clearInterval(timer);
  27. if(Fn)Fn();//当目标运动完成,执行回调函数
  28. }
  29. }
  30. },30);
  31. }
  32.  
  33. function getStyle(obj,prop){//获取css样式值
  34. if(obj.currentStyle){//IE
  35. return obj.currentStyle(prop);
  36. }else{//其他
  37. return getComputedStyle(obj,false)[prop];
  38. }
  39. }

BOM之定时器的更多相关文章

  1. BOM以及定时器

    一.BOM 1.操作浏览器的一些方法 (浏览器对象模型) 2.window是is中的顶级变量,是一个全局的变量,所有人都可以访问到它,基本 的方法和属性 (document,alert,console ...

  2. 13 -1 BOM和定时器

    一 BOM JavaScript基础分为三个部分: ECMAScript:JavaScript的语法标准.包括变量.表达式.运算符.函数.if语句.for语句等. DOM:文档对象模型,操作网页上的元 ...

  3. BOM心得-定时器

    写在前面的话:之前一直以为定时器的返回值是Object类型,所以timer初始化也是写null,今天发现返回值是number,进而发觉这个返回值代表的是定时器的索引,指代这是第几个定时器 个人觉得只用 ...

  4. JS中定时器的返回数值ID值

    定时器会返回一个数字值id,可以由clearInterval(id)或clearTimeout(id)来实现对对应定时器的清除. setInterval()/setTimeout()BOM中的Wind ...

  5. web前端面试第一次[定时器]

    BOM中定时器--计时器 定时器参数两个:(函数,时间(单位ms(1000ms=1s))) 时间设置1s,每过1s执行一次函数 //设置定时器 setInterval(funtion(){ alert ...

  6. 前端3 — js — BOM没完( 不了解也行 )

    1.js是什么? -- 英文全称javascript javaScript(简称"JS") 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言.虽然它是作为开发Web页面的脚 ...

  7. Web前端学习路线

    第一阶段: HTML+CSS:HTML进阶.CSS进阶.div+css布局.HTML+css整站开发. JavaScript基础:Js基础教程.js内置对象常用方法.常见DOM树操作大全.ECMAsc ...

  8. 关于web前端的学习路线

    第一阶段: HTML+CSS:HTML进阶.CSS进阶.div+css布局.HTML+css整站开发. JavaScript基础:Js基础教程.js内置对象常用方法.常见DOM树操作大全.ECMAsc ...

  9. (1)写给Web初学者的教案-----学习Web的知识架构

    1:学习Web的知识架构 前文中我们简单的介绍了一些关于Web的基本知识,这里任老师再次强调一下凡是用浏览器打开的网站我们就称之为Web应用程序(B/S结构).除此之外其它需要下载安装的软件或是手机  ...

随机推荐

  1. MySQL基础(用的贼鸡儿多)

    整理有点乱,业余也玩玩系统,经常碰见这些玩意,有点烦,老是记不住 MySQL 基础语法 一.连接 MYSQL格式: mysql -h 主机地址 -u 用户名 -p 用户密码. 1.连接到本机上的 MY ...

  2. Javaweb之国际化

    Javaweb之国际化 一.前言 软件的本地化:一个软件在某个国家或地区使用时,采用该国家或地区的语言,数字,货币,日期等习惯. 软件的国际化:软件开发时,让它能支持多个国家和地区的本地化应用.使得应 ...

  3. Java多线程之线程的启动

    Java多线程之线程的启动 一.前言 启动线程的方法有如下两种. 利用Thread 类的子类的实例启动线程 利用Runnable 接口的实现类的实例启动线程 最后再介绍下java.util.concu ...

  4. Java IO体系综述

    Java IO体系综述 一.流的概念 在Java API中,可以从其中读入一个字节序列的对象称作输入流,而可以向其中写入一个字节序列的对象称作输出流.这些字节序列的来源地和目的地可以是文件,而且通常都 ...

  5. 【朝花夕拾】Handler篇(二)

    前言 一年前写过一篇文章[朝花夕拾]Handler篇,随着这一年来对Handler更多的认识和理解,本文对Handler知识点做的一些补充. 一.为什么要引入Handler Handler的主要作用是 ...

  6. .net core api服务端跨域配置

    第1步:添加包引用(.net core 2.2 已自带此包,可跳过此步骤) Install-Package Microsoft.AspNetCore.Cors 第2步:在Startup.cs文件的Co ...

  7. https免费证书申请certbot,nginx

    官网:https://certbot.eff.org/ 下载: wget https://dl.eff.org/certbot-auto chmod a+x certbot-auto ./certbo ...

  8. 2014 西安 The Problem Needs 3D Arrays

    The Problem Needs 3D Arrays 题意:给你n个数, 然后1-n的数, 然后要求按顺序选出m个数, 求 逆序数/m 个数的 最大值是多少. 题解:裸的最大密度子图.逆序的2个数建 ...

  9. hdu 3577 Fast Arrangement(线段树区间修改,求区间最小值)

    Problem Description Chinese always have the railway tickets problem because of its' huge amount of p ...

  10. MPA JS CSS预处理方案

    1.WebPack 添加配置文件webpack.config.js,直接在当前目录运行 webpack. var basepath = '/root/webapps/happ'; var glob = ...