javascript
【JavaScript】【5】定时器(包含回调函数与Promise)
文章目錄
- 前言
- 一、回調(diào)函數(shù)
- 二、 Promise
- promise對象
- Promise對象的生成
- 加載圖片寫成一個(gè)Promise
- 三、定時(shí)器與清除定時(shí)器的方法
- 四、京東購物車倒計(jì)時(shí)案例
- 五、發(fā)送驗(yàn)證碼案例
- 在這里插入圖片描述
- 總結(jié)
前言
什么是定時(shí)器
JavaScript提供定時(shí)執(zhí)行代碼的功能,叫做定時(shí)器(timer),主要由setTimeout()和setInterval()這兩個(gè)函數(shù)來完成。它們向任務(wù)隊(duì)列添加定時(shí)任務(wù)。
了解回調(diào)函數(shù)和Promise對象
一、回調(diào)函數(shù)
- 你不知道用戶何時(shí)單擊按鈕。 因此,為點(diǎn)擊事件定義了一個(gè)事件處理程序。 該事件處理程序會接受一個(gè)函數(shù),該函數(shù)會在該事件被觸發(fā)時(shí)被調(diào)用。
- 回調(diào)是一個(gè)簡單的函數(shù),會作為值被傳給另一個(gè)函數(shù),并且僅在事件發(fā)生時(shí)才被執(zhí)行。 之所以這樣做,是因?yàn)?JavaScript 具有頂級的函數(shù),這些函數(shù)可以被分配給變量并傳給其他函數(shù)(稱為高階函數(shù))。通常會將所有的客戶端代碼封裝在 window 對象的 load 事件監(jiān)聽器中,其僅在頁面準(zhǔn)備就緒時(shí)才會運(yùn)行
- 回調(diào)無處不在,不僅在 DOM 事件中。一個(gè)常見的示例是使用定時(shí)器:
- XHR 請求也接受回調(diào),在此示例中,會將一個(gè)函數(shù)分配給一個(gè)屬性,該屬性會在發(fā)生特定事件(在該示例中,是請求狀態(tài)的改變)時(shí)被調(diào)用:
- 回調(diào)適用于簡單的場景!但是,每個(gè)回調(diào)都可以添加嵌套的層級,并且當(dāng)有很多回調(diào)時(shí),代碼就會很快變得非常復(fù)雜
這是一個(gè)簡單的四級嵌套,但是當(dāng)嵌套越來越復(fù)雜時(shí),不推薦使用多級嵌套。從 ES6 開始,JavaScript 引入了一些特性,可以幫助處理異步代碼而不涉及使用回調(diào):Promise(ES6)和 Async/Await(ES2017)。
二、 Promise
promise對象
Promise對象是CommonJS工作組提出的一種規(guī)范,目的是為異步操作提供統(tǒng)一接口。
首先,它是一個(gè)對象,也就是說與其他JavaScript對象的用法,沒有什么兩樣;其次,它起到代理作用(proxy),充當(dāng)異步操作與回調(diào)函數(shù)之間的中介。它使得異步操作具備同步操作的接口,使得程序具備正常的同步運(yùn)行的流程,回調(diào)函數(shù)不必再一層層嵌套。
簡單說,它的思想是,每一個(gè)異步任務(wù)立刻返回一個(gè)Promise對象,由于是立刻返回,所以可以采用同步操作的流程。這個(gè)Promises對象有一個(gè)then方法,允許指定回調(diào)函數(shù),在異步任務(wù)完成后調(diào)用。
- 異步操作f1返回一個(gè)Promise對象,它的回調(diào)函數(shù)f2寫法如下
- 多層回調(diào)函數(shù)
總的來說,傳統(tǒng)的回調(diào)函數(shù)寫法使得代碼混成一團(tuán),變得橫向發(fā)展而不是向下發(fā)展。Promises規(guī)范就是為了解決這個(gè)問題而提出的,目標(biāo)是使用正常的程序流程(同步),來處理異步操作。它先返回一個(gè)Promise對象,后面的操作以同步的方式,寄存在這個(gè)對象上面。等到異步操作有了結(jié)果,再執(zhí)行前期寄放在它上面的其他操作。
- Promise對象的三種狀態(tài):
異步操作“未完成”(pending)
異步操作“已完成”(resolved,又稱fulfilled)
異步操作“失敗”(rejected)
三種途徑的變換方式只有兩種:從未完成到已完成和從未完成到失敗 - 變換方式只能發(fā)生一次,一旦狀態(tài)變?yōu)?#34;已完成"或"失敗",就意味著不會發(fā)生新的狀態(tài)變化了。Promise對象的最終狀態(tài)只有兩種
異步操作成功:Promise對象傳回一個(gè)值,狀態(tài)變?yōu)閞esolved
異步操作失敗,Promise對象拋出一個(gè)錯(cuò)誤,狀態(tài)變?yōu)閞ejected
- then方法可以鏈?zhǔn)绞褂?/li>
從同步角度看等價(jià)于
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); //在異步操作成功時(shí)調(diào)用,并將異步操作的結(jié)果,作為參數(shù)傳遞出去 }else{reject(error); //在異步操作失敗時(shí)調(diào)用,并將異步操作報(bào)出的錯(cuò)誤,作為參數(shù)傳遞出去 } })可以使用then方法
po.then(function(value){//success },function(value){//failure });加載圖片寫成一個(gè)Promise
var preloadImage = function(path){return new Promise(function(resolve,reject){var image = new Image();image.onload = resolve;image.onerror = reject;image.src = path;}) }三、定時(shí)器與清除定時(shí)器的方法
1 推遲執(zhí)行的代碼必須以字符串的形式,放入setTimerout
因?yàn)橐鎯?nèi)部使用eval函數(shù),將字符串轉(zhuǎn)化為代碼。
2 如果推遲執(zhí)行的是函數(shù),則可以直接將函數(shù)名,放入setTimeout。
一方面eval函數(shù)有安全顧慮,另一方面為了便于JavaScript引擎優(yōu)化代碼,setTimeout方法一般總是采用函數(shù)名的形式
3 清除定時(shí)器
function fn(){console(2); } var timer = setTimeout(fn,1000); clearTimeout(timer);四、京東購物車倒計(jì)時(shí)案例
布局省略代碼如下(示例):
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(); //返回當(dāng)前毫秒數(shù)var time = (inputTime - nowTime) / 1000; //時(shí)間差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;}五、發(fā)送驗(yàn)證碼案例
布局省略代碼如下(示例):
//1 按鈕點(diǎn)擊后,禁用按鈕//2 同時(shí)按鈕里面的內(nèi)容會變化,主要button里面的內(nèi)容通過innerHTML修改//3 秒數(shù)定義一個(gè)變量在定時(shí)器里不斷遞減//4 如果變量為0說明時(shí)間到了,停止計(jì)數(shù)器,并復(fù)原按鈕初始狀態(tài)var button = document.querySelector('button');var time = 10;button.addEventListener('click',function(){button.disabled = true;var timer = setInterval(()=>{if(time == 0){//清除定時(shí)器和復(fù)原按鈕clearInterval(timer);button.disabled = false;button.innerHTML = '發(fā)送'; time = 10;}else{button.innerHTML = '還剩'+time+'秒發(fā)送';--time;}},1000)})// while(time == 0){// button.disabled = false;// button.innerHTML = '發(fā)送驗(yàn)證碼';// }盡量不去使用while總結(jié)
提示:這里對文章進(jìn)行總結(jié):
Promise對象還需要繼續(xù)學(xué)習(xí)。定時(shí)器要學(xué)會計(jì)數(shù)和清除
總結(jié)
以上是生活随笔為你收集整理的【JavaScript】【5】定时器(包含回调函数与Promise)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hypermesh抽中面后的处理_总结|
- 下一篇: JS 定时器的2种写法及介绍