javascript
【JavaScript】【5】定时器(包含回调函数与Promise)
文章目錄
- 前言
- 一、回調函數
- 二、 Promise
- promise對象
- Promise對象的生成
- 加載圖片寫成一個Promise
- 三、定時器與清除定時器的方法
- 四、京東購物車倒計時案例
- 五、發送驗證碼案例
- 在這里插入圖片描述
- 總結
前言
什么是定時器
JavaScript提供定時執行代碼的功能,叫做定時器(timer),主要由setTimeout()和setInterval()這兩個函數來完成。它們向任務隊列添加定時任務。
了解回調函數和Promise對象
一、回調函數
- 你不知道用戶何時單擊按鈕。 因此,為點擊事件定義了一個事件處理程序。 該事件處理程序會接受一個函數,該函數會在該事件被觸發時被調用。
- 回調是一個簡單的函數,會作為值被傳給另一個函數,并且僅在事件發生時才被執行。 之所以這樣做,是因為 JavaScript 具有頂級的函數,這些函數可以被分配給變量并傳給其他函數(稱為高階函數)。通常會將所有的客戶端代碼封裝在 window 對象的 load 事件監聽器中,其僅在頁面準備就緒時才會運行
- 回調無處不在,不僅在 DOM 事件中。一個常見的示例是使用定時器:
- XHR 請求也接受回調,在此示例中,會將一個函數分配給一個屬性,該屬性會在發生特定事件(在該示例中,是請求狀態的改變)時被調用:
- 回調適用于簡單的場景!但是,每個回調都可以添加嵌套的層級,并且當有很多回調時,代碼就會很快變得非常復雜
這是一個簡單的四級嵌套,但是當嵌套越來越復雜時,不推薦使用多級嵌套。從 ES6 開始,JavaScript 引入了一些特性,可以幫助處理異步代碼而不涉及使用回調:Promise(ES6)和 Async/Await(ES2017)。
二、 Promise
promise對象
Promise對象是CommonJS工作組提出的一種規范,目的是為異步操作提供統一接口。
首先,它是一個對象,也就是說與其他JavaScript對象的用法,沒有什么兩樣;其次,它起到代理作用(proxy),充當異步操作與回調函數之間的中介。它使得異步操作具備同步操作的接口,使得程序具備正常的同步運行的流程,回調函數不必再一層層嵌套。
簡單說,它的思想是,每一個異步任務立刻返回一個Promise對象,由于是立刻返回,所以可以采用同步操作的流程。這個Promises對象有一個then方法,允許指定回調函數,在異步任務完成后調用。
- 異步操作f1返回一個Promise對象,它的回調函數f2寫法如下
- 多層回調函數
總的來說,傳統的回調函數寫法使得代碼混成一團,變得橫向發展而不是向下發展。Promises規范就是為了解決這個問題而提出的,目標是使用正常的程序流程(同步),來處理異步操作。它先返回一個Promise對象,后面的操作以同步的方式,寄存在這個對象上面。等到異步操作有了結果,再執行前期寄放在它上面的其他操作。
- Promise對象的三種狀態:
異步操作“未完成”(pending)
異步操作“已完成”(resolved,又稱fulfilled)
異步操作“失敗”(rejected)
三種途徑的變換方式只有兩種:從未完成到已完成和從未完成到失敗 - 變換方式只能發生一次,一旦狀態變為"已完成"或"失敗",就意味著不會發生新的狀態變化了。Promise對象的最終狀態只有兩種
異步操作成功:Promise對象傳回一個值,狀態變為resolved
異步操作失敗,Promise對象拋出一個錯誤,狀態變為rejected
- then方法可以鏈式使用
從同步角度看等價于
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函數,將字符串轉化為代碼。
2 如果推遲執行的是函數,則可以直接將函數名,放入setTimeout。
一方面eval函數有安全顧慮,另一方面為了便于JavaScript引擎優化代碼,setTimeout方法一般總是采用函數名的形式
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對象還需要繼續學習。定時器要學會計數和清除
總結
以上是生活随笔為你收集整理的【JavaScript】【5】定时器(包含回调函数与Promise)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hypermesh抽中面后的处理_总结|
- 下一篇: gradle idea java ssm