首页IT科技javascript的成熟分类(【JavaScript】【5】定时器(包含回调函数与Promise))

javascript的成熟分类(【JavaScript】【5】定时器(包含回调函数与Promise))

时间2025-08-04 04:38:40分类IT科技浏览4455
导读:前言 什么是定时器 JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout( 和setInterval( 这两个函数来完成。它们向任务队列添加定时任务。...

前言

什么是定时器

JavaScript提供定时执行代码的功能              ,叫做定时器(timer)                      ,主要由setTimeout()和setInterval()这两个函数来完成              。它们向任务队列添加定时任务                      。

了解回调函数和Promise对象

一              、回调函数

你不知道用户何时单击按钮      。 因此      ,为点击事件定义了一个事件处理程序          。 该事件处理程序会接受一个函数          ,该函数会在该事件被触发时被调用                       。 回调是一个简单的函数                       ,会作为值被传给另一个函数         ,并且仅在事件发生时才被执行         。 之所以这样做      ,是因为 JavaScript 具有顶级的函数                       ,这些函数可以被分配给变量并传给其他函数(称为高阶函数)      。通常会将所有的客户端代码封装在 window 对象的 load 事件监听器中             ,其仅在页面准备就绪时才会运行 window.addEventListener(load, () => { //window 已被加载                       。 //做需要做的             。 }) 回调无处不在   ,不仅在 DOM 事件中   。一个常见的示例是使用定时器: setTimeout(() => { // 2 秒之后运行                      。 }, 2000) XHR 请求也接受回调                      ,在此示例中                 ,会将一个函数分配给一个属性,该属性会在发生特定事件(在该示例中                  ,是请求状态的改变)时被调用: const xhr = new XMLHttpRequest() xhr.onreadystatechange = () => { if (xhr.readyState === 4) { xhr.status === 200 ? console.log(xhr.responseText) : console.error(出错) } } xhr.open(GET, http://nodejs.cn) xhr.send() 回调适用于简单的场景!但是                     ,每个回调都可以添加嵌套的层级   ,并且当有很多回调时              ,代码就会很快变得非常复杂 window.addEventListener(load, () => { document.getElementById(button).addEventListener(click, () => { setTimeout(() => { items.forEach(item => { //你的代码在这里                 。 }) }, 2000) }) })

这是一个简单的四级嵌套                      ,但是当嵌套越来越复杂时      ,不推荐使用多级嵌套。从 ES6 开始          ,JavaScript 引入了一些特性                       ,可以帮助处理异步代码而不涉及使用回调:Promise(ES6)和 Async/Await(ES2017)                  。

二                      、 Promise

promise对象

Promise对象是CommonJS工作组提出的一种规范         ,目的是为异步操作提供统一接口                     。

首先      ,它是一个对象                       ,也就是说与其他JavaScript对象的用法             ,没有什么两样;其次   ,它起到代理作用(proxy)                      ,充当异步操作与回调函数之间的中介   。它使得异步操作具备同步操作的接口                 ,使得程序具备正常的同步运行的流程,回调函数不必再一层层嵌套              。

简单说                  ,它的思想是                     ,每一个异步任务立刻返回一个Promise对象   ,由于是立刻返回              ,所以可以采用同步操作的流程                      。这个Promises对象有一个then方法                      ,允许指定回调函数      ,在异步任务完成后调用      。 异步操作f1返回一个Promise对象          ,它的回调函数f2写法如下 (new Promise(f1)).then(f2) 多层回调函数 //传统写法 step1(function(value1){ step2(value1,function(value2){ step3(value2,function(value3){ step4(value3,function(value4){ ... }) }) }) }) //Promise写法 (new Promise(step1)) .then(step2); .then(step3); .then(step4);

总的来说                       ,传统的回调函数写法使得代码混成一团         ,变得横向发展而不是向下发展          。Promises规范就是为了解决这个问题而提出的      ,目标是使用正常的程序流程(同步)                       ,来处理异步操作                       。它先返回一个Promise对象             ,后面的操作以同步的方式   ,寄存在这个对象上面         。等到异步操作有了结果                      ,再执行前期寄放在它上面的其他操作      。

Promise对象的三种状态:

异步操作“未完成              ”(pending)

异步操作“已完成                    ”(resolved                 ,又称fulfilled)

异步操作“失败        ”(rejected)

三种途径的变换方式只有两种:从未完成到已完成和从未完成到失败 变换方式只能发生一次,一旦状态变为"已完成"或"失败"                  ,就意味着不会发生新的状态变化了                       。Promise对象的最终状态只有两种

异步操作成功:Promise对象传回一个值                     ,状态变为resolved

异步操作失败   ,Promise对象抛出一个错误              ,状态变为rejected // po是一个Promise对象 //Promise对象po使用then方法绑定两个回调函数                      ,操作成功返回console.log      ,操作失败返回console.error          ,这两个函数都接受异步操作传回的值作为参数 po.then( console.log, console.error ); then方法可以链式使用 po .then(step1) .then(step2) .then(step3) .then{ console.log; console.error; //Promise对象的错误有传递性 }

从同步角度看等价于

try { var v1 = step1(po); var v2 = step2(v1); var v3 = step3(v2); console.log(v3); } catch (error) { console.error(error); }

Promise对象的生成

var promise = new Promise(function(resolve,reject){ if(/*异步操作成功*/){ resolve(value); //在异步操作成功时调用                       ,并将异步操作的结果         ,作为参数传递出去 }else{ reject(error); //在异步操作失败时调用      ,并将异步操作报出的错误                       ,作为参数传递出去 } })

可以使用then方法

po.then(function(value){ //success },function(value){ //failure });

加载图片写成一个Promise

var preloadImage = function(path){ return new Promise(function(resolve,reject){ var image = new Image(); image.onload = resolve; image.onerror = reject; image.src = path; }) }

三      、定时器与清除定时器的方法

1

推迟执行的代码必须以字符串的形式             ,放入setTimerout

因为引擎内部使用eval函数   ,将字符串转化为代码             。 setTimeout(console.log(1),1000)

2

如果推迟执行的是函数                      ,则可以直接将函数名                 ,放入setTimeout   。

一方面eval函数有安全顾虑,另一方面为了便于JavaScript引擎优化代码                  ,setTimeout方法一般总是采用函数名的形式 function fn(){ console.log(2); } setTimeout(fn,1000); //或者 setTimeout(function(){ console.log(2); },1000)

3 清除定时器

function fn(){ console(2); } var timer = setTimeout(fn,1000); clearTimeout(timer);

四          、京东购物车倒计时案例

布局省略代码如下(示例):

var day = document.querySelector(.day) var hour = document.querySelector(".hour"); var minute = document.querySelector(.minute); var second = document.querySelector(".second"); var inputTime = +new Date(2022-6-4 22:00:00) countDown(); var timer = null; timer = setInterval(countDown,1000); var button2 = document.querySelector(.start); button2.addEventListener(click,()=>{ timer = setInterval(countDown,1000); }) var button = document.querySelector(.stop); button.addEventListener(click,function(){ clearTimeout(timer); }) function countDown(){ var nowTime = +new Date(); //返回当前毫秒数 var time = (inputTime - nowTime) / 1000; //时间差 var d = parseInt(time / 60 / 60 /24); d = d < 10 ? 0+d : d; day.innerHTML = d; var h = parseInt(time / 60 / 60 %24); h = h < 10? 0+h : h; hour.innerHTML = h; var m = parseInt(time / 60 % 60); m = m < 10? 0+m : m; minute.innerHTML = m; var s = parseInt(time % 60) s = s <10? 0+s : s; second.innerHTML = s; }

五                       、发送验证码案例

布局省略代码如下(示例):

//1 按钮点击后                     ,禁用按钮 //2 同时按钮里面的内容会变化   ,主要button里面的内容通过innerHTML修改 //3 秒数定义一个变量在定时器里不断递减 //4 如果变量为0说明时间到了              ,停止计数器                      ,并复原按钮初始状态 var button = document.querySelector(button); var time = 10; button.addEventListener(click,function(){ button.disabled = true; var timer = setInterval(()=>{ if(time == 0){ //清除定时器和复原按钮 clearInterval(timer); button.disabled = false; button.innerHTML = 发送; time = 10; }else{ button.innerHTML = 还剩+time+秒发送; --time; } },1000) }) // while(time == 0){ // button.disabled = false; // button.innerHTML = 发送验证码; // }尽量不去使用while

总结

提示:这里对文章进行总结:

Promise对象还需要继续学习                      。定时器要学会计数和清除
声明:本站所有文章      ,如无特殊说明或标注          ,均为本站原创发布                 。任何个人或组织                       ,在未征得本站同意时         ,禁止复制         、盗用      、采集                       、发布本站内容到任何网站             、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益      ,可联系我们进行处理                  。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
服务器测速带宽命令(speedtest-cli命令 – 测试服务器外网速度) 进程间通信的几种方法(asmproserver.exe是什么进程 asmproserver进程信息查询)