寫在前面
在使用keyup事件時,存在一個問題,假如想要做出類似於表單驗證的demo:表單輸入賬號 “xxx” 后 再去ajax異步去后台數據庫匹配,但是keyup事件的原理是每次鍵盤事件彈起就會檢測,也就是輸入“x”的時候就會檢測,所以輸入“xxx”就會使用三次ajax,這樣的用戶體驗是不好的。再舉一個例子,再用百度的時候,打開www.baidu.com 輸入任意一個字符,就會自動彈出關於該字符的搜索信息,我感覺這個用戶體驗不好,我在輸入一個字符的時候,百度搜索框下面某個新聞我很感興趣,但是頁面已經跳轉,我history(-1)時,發現新聞頁已經刷新了。這樣我就看不到我想要看的新聞了。所以在輸入“xxx”完整的字符再觸發keyup事件顯得比較重要。
如何實現
這個問題就是keyup事件延遲的問題。如何實現,很簡單,就是使用定時器setTimeout和event.timeStamp。假設定期器為1000ms,定時器負責1000ms后觸發keyup事件,setTimeout的原理就是,把當前事件的執行結果放入事件循環中,待JS引擎空閑時再去處理執行結果。event.timeStamp是一個事件的時間戳,表示發生事件的時間和日期(從 epoch 開始的毫秒數)epoch 是一個事件參考點。在這里,它是客戶機啟動的時間。
在keyup事件中引用event.timeStamp,last = event.timeStamp
在定時器中進行判斷 if(last==event.timeStamp) 為真 則執行ajax
原理就是,last代表最后一次keyup的時間戳,你停止輸入1000ms內沒有再次觸發keyup事件,則執行ajax,用代碼表示就是(last==event.timeStamp)為真,如果你1000ms又觸發了keyup事件,則繼續判斷,如果你停止輸入1000ms內沒有再次觸發keyup事件,則執行ajax。
用代碼完成
js:
// <input type="text" id="input"> $(function(){ $("#input").focus(); $("#input").on("keyup",function(e){ $this = $(this); last = e.timeStamp; setTimeout(function(){ // console.log(e.timeStamp); var $data_data = $this.val(); if(last-e.timeStamp===0){ $.ajax({ type:"get", url:"ajaxkeyup.php", data:{ $data:$data_data }, success:function(data){ console.log("ajax發送並接收響應成功顯示的ok"); console.log(data); }, onerror:function(){ console.log("not ok"); } }) } },1000) }) })
php:
<?php $data = '123'; $getData = $_GET['$data']; if ($getData==$data) { echo "后台檢測匹配失敗顯示的ok"; }else{ echo "后台檢測匹配失敗顯示的failed"; } ?>
模擬數據庫的數據為“123”,完整輸入“123”后 執行ajax
demo如下
有點不清晰,但是效果就是當輸入"123"時 觸發keyup事件,執行ajax,顯示ajax發送並接收成功,后台服務器也返回成功
當輸入“1234”時,ajax發送並接收成功,但是后台檢測失敗
總結
這個問題是面試商湯科技唄問的問題,上一個被問的問題是promise實現紅綠燈,這個問題是keyup事件的延遲。都使用了異步的操作方式,螞蟻金服面試的時候也問JS有哪些異步操作,看來異步操作是JS的核心之一。
定時器setTimeout與異步ajax同時執行,既有頁面無刷新的魅力也有事件循環的感覺。爽。