ฟังก์ชั่นการควบคุมปริมาณเพียงแค่ทำให้ฟังก์ชั่นไม่สามารถเรียกได้อย่างต่อเนื่องภายในช่วงเวลาสั้น ๆ เฉพาะเมื่อมีการดำเนินการฟังก์ชั่นสุดท้ายหลังจากช่วงเวลาที่ระบุโดยคุณสามารถเรียกใช้ฟังก์ชันต่อไปได้
หลักการของการควบคุมปริมาณฟังก์ชั่นนั้นค่อนข้างง่าย ฉันเดาว่าทุกคนคิดว่ามันคือตัวจับเวลา เมื่อฉันทริกเกอร์เวลาก่อนที่จะชะลอกิจกรรมไปสักพักก่อนการดำเนินการ หากเหตุการณ์ถูกทริกเกอร์อีกครั้งภายในช่วงเวลานี้เราจะล้างตัวจับเวลาดั้งเดิมแล้วตั้งค่าตัวจับเวลาใหม่เพื่อชะลอการดำเนินการในขณะที่นั่นคือ
ในสถานการณ์ต่อไปนี้สถานการณ์ต่อไปนี้มักจะทำพฤติกรรมหนักเช่นการดำเนินงาน DOM และการโหลดทรัพยากรทำให้ UI หยุดชั่วคราวหรือแม้แต่เบราว์เซอร์ล่ม
1. ปรับขนาดและเลื่อนเหตุการณ์ของวัตถุหน้าต่าง
2. เหตุการณ์ Mousemove ระหว่างการลาก
3. กิจกรรม Mousedown และ Keydown ในเกมถ่ายภาพ
4. เหตุการณ์ KeyUp ที่เสร็จสมบูรณ์โดยการป้อนข้อความโดยอัตโนมัติ
ในความเป็นจริงสำหรับเหตุการณ์การปรับขนาดของหน้าต่างข้อกำหนดที่แท้จริงคือการหยุดเปลี่ยนขนาด n มิลลิวินาทีและดำเนินการประมวลผลที่ตามมา ในขณะที่เหตุการณ์อื่น ๆ ส่วนใหญ่ต้องการการประมวลผลที่ตามมาในความถี่ที่แน่นอน มีวิธีแก้ปัญหาสองประการสำหรับความต้องการทั้งสองนี้คือ Debounce และ Throttle
คันเร่งและ debounce เป็นสองวิธีแก้ปัญหาการร้องขอและความเร็วในการตอบสนองไม่ตรงกัน ความแตกต่างระหว่างทั้งสองอยู่ในการเลือกกลยุทธ์ที่แตกต่างกัน
ดำเนินการฟังก์ชั่นในช่วงเวลาต่าง ๆ เช่นคันเร่ง
หากเหตุการณ์ถูกทริกเกอร์อีกครั้งภายในช่วงเวลา debounce T ตัวจับเวลาจะถูกกำหนดเวลาอีกครั้งจนกว่าจะถึงเวลาหยุดมากกว่าหรือเท่ากับ T
1. การใช้งานฟังก์ชั่นคันเร่งอย่างง่าย
ฟังก์ชั่นเค้น (fn, threshhold, ขอบเขต) {threshhold || (threshhold = 250); var สุดท้ายตัวจับเวลา; return function () {var context = ขอบเขต || นี้; var now = +วันที่ใหม่ (), args = อาร์กิวเมนต์; if (สุดท้าย && ตอนนี้ - สุดท้าย + threshhold <0) {// ret ต่อไป cleartimeout (defertimer); timer = settimeout (function () {last = now; fn.apply (บริบท, args);}, threshhold); } else {last = ตอนนี้; fn.apply (บริบท, args); -วิธีการโทร
$ ('body'). on ('mousemove', เค้น (ฟังก์ชั่น (เหตุการณ์) {console.log ('tick');}, 1000));2. การใช้งานฟังก์ชัน debounce อย่างง่าย
ฟังก์ชั่น debounce (fn, ล่าช้า) {var timer = null; return function () {var context = this, args = อาร์กิวเมนต์; ClearTimeout (ตัวจับเวลา); timer = settimeout (function () {fn.apply (บริบท, args);}, ล่าช้า); -วิธีการโทร
$ ('input.username'). keypress (debounce (ฟังก์ชั่น (เหตุการณ์) {// ทำคำขอ AJAX}, 250));3. การใช้บรรจุภัณฑ์แบบง่าย ๆ
/** * คันเร่ง * @param fn, รอ, debounce */var throttle = function (fn, รอ, debounce) {var timer = null, // ตัวจับเวลา t_last = null, // ชุดครั้งสุดท้าย, // บริบท args, // พารามิเตอร์ diff; // ความแตกต่างของเวลาส่งคืน funciton () {var curr = + วันที่ใหม่ (); var context = this, args = อาร์กิวเมนต์; ClearTimeout (ตัวจับเวลา); if (debounce) {// ถ้ามันเป็น debounce timer = settimeout (function () {fn.apply (บริบท, args);}, รอ); } else {// ถ้ามันเป็นคันเร่งถ้า (! t_last) t_last = curr; if (curr - t_last> = รอ) {fn.apply (บริบท, รอ); บริบท = รอ = null; }}}}/** * debounce * @param fn, รอ */var debounce = function (fn, รอ) {return throttle (fn, wait, true);}สรุป: ทั้งสองวิธีนี้เหมาะสำหรับเหตุการณ์บางอย่างที่จะถูกเรียกซ้ำ ๆ เช่น: Mousemove, Keydown, Keyup, Keypress, Scroll ฯลฯ
หากคุณเชื่อมโยงเหตุการณ์ดั้งเดิมเท่านั้นและไม่ควบคุมพวกเขาเบราว์เซอร์จะถูกพูดติดอ่างและประสบการณ์ผู้ใช้จะไม่ดี เพื่อปรับปรุงประสิทธิภาพของ JS ขอแนะนำให้ใช้ฟังก์ชั่นการควบคุมปริมาณหรือฟังก์ชั่น debounce เพื่อควบคุมเมื่อใช้เหตุการณ์ข้างต้นและเหตุการณ์ที่คล้ายกัน
4. การวิเคราะห์ซอร์สโค้ดที่เกี่ยวข้องกับขีดล่าง v1.7.0
1. _. throttle function
_.throttle = ฟังก์ชั่น (func, รอ, ตัวเลือก) {บริบท var, args, ผลลัพธ์; var timeout = null; // ตัวจับเวลา var ก่อนหน้า = 0; // เวลาที่เรียกใช้ครั้งสุดท้ายถ้า (! ตัวเลือก) ตัวเลือก = {}; var later = function () {previous = options.leading === false? 0: _.now (); หมดเวลา = null; ผลลัพธ์ = func.apply (บริบท, args); ถ้า (! หมดเวลา) บริบท = args = null; - return function () {var now = _.now (); // ว่าจะเรียกใช้งาน if (! ก่อนหน้า && opotions.leading === false) ก่อนหน้า = ตอนนี้; // นี่คือแนวคิดของการเหลืออยู่: เวลาเหลือนานเท่าใดในการดำเนินการเหตุการณ์ที่เหลืออยู่ = รอ - (ตอนนี้ - ก่อนหน้า); บริบท = สิ่งนี้; args = อาร์กิวเมนต์; // ที่เหลืออยู่ <= 0 เมื่อพิจารณาว่าเหตุการณ์จะถูกลองใหม่หลังจากเหตุการณ์หยุดทำงานหรือ // เมื่อการรอคอยแตกต่างกันอย่างแน่นอนเหตุการณ์จะถูกเรียกทันที // ยังคงอยู่> การรอคอยไม่ได้คำนึงถึงสถานการณ์ที่สอดคล้องกัน // เพราะตอนนี้มีค่าบวกอยู่เสมอ เหลืออยู่> รอ) {ถ้า (หมดเวลา) {ClearTimeOut (หมดเวลา); หมดเวลา = null; } previous = ตอนนี้; ผลลัพธ์ = func.apply (บริบท, args); ถ้า (! หมดเวลา) บริบท = args = null; // ว่าจะติดตาม} อื่นถ้า (! หมดเวลา && ตัวเลือก trailing! == false) {timeout = settimeout (ในภายหลังที่เหลือ); } ผลตอบแทนผลลัพธ์; -ดังที่เห็นได้จากข้างต้นขีดความสามารถของขีดความสามารถได้พิจารณาสถานการณ์มากขึ้น: ตัวเลือกการเรียนรู้:
ครั้งแรกจะถูกดำเนินการค่าเริ่มต้นเป็นจริงซึ่งหมายความว่าครั้งแรกจะถูกดำเนินการ ตัวเลือกการดำเนินการครั้งแรกการ trailing ถูกปิดใช้งาน: ครั้งสุดท้ายจะถูกดำเนินการค่าเริ่มต้นคือจริงซึ่งหมายความว่าครั้งสุดท้ายจะถูกดำเนินการ ครั้งสุดท้ายจะผ่าน {trailing: false} หมายความว่าครั้งสุดท้ายจะไม่ถูกดำเนินการ ครั้งแรกที่เรียกว่าเหตุการณ์จะถูกดำเนินการก่อนหรือไม่ เมื่อเหตุการณ์เริ่มต้นขึ้นไม่ว่าเหตุการณ์ควรจะถูกเรียกใช้ก่อนหรือไม่ หากคุณต้องการก่อนหน้า = 0 และที่เหลืออยู่เป็นลบซึ่งเรียกว่าครั้งสุดท้ายว่าฟังก์ชันจะถูกเรียกใช้งานทันทีหลังจากเหตุการณ์สิ้นสุดลง วิธีนี้จะถูกกระตุ้นในครั้งสุดท้าย หากคุณต้องการดำเนินการตัวจับเวลาจะถูกตั้งค่านั่นคือจะต้องดำเนินการหนึ่งครั้งหลังจากเหตุการณ์สิ้นสุดลง remianing> รอหมายความว่าเวลาของลูกค้าได้รับการแก้ไขแล้ว
2. _.debounce ฟังก์ชั่น
_.debounce = function (func, รอ, ทันที) {// ค่าเริ่มต้นทันทีคือ Talse var timeout, args, บริบท, timestamp, ผลลัพธ์; var later = function () {// เมื่อฟังก์ชั่นส่งคืนโดย _.debounce เรียกว่าหลายครั้งในช่วงเวลาที่ระบุโดยรอค่าของการประทับเวลาจะได้รับการอัปเดตอย่างต่อเนื่องส่งผลให้ <รอ && สุดท้าย> = 0 เป็นจริงเสมอ ถ้า (สุดท้าย <wait && last> = 0) {timeout = settimeout (ในภายหลังรอ - สุดท้าย); } else {timeout = null; if (! ทันที) {result = func.apply (บริบท, args); ถ้า (! หมดเวลา) บริบท = args = null; - return function () {context = this; args = อาร์กิวเมนต์; timestamp = _.now (); // เมื่อวิธีการที่เรียกว่าครั้งแรกและทันทีหลังจากช่วงเวลาที่ระบุโดยการรอเวลาจะเริ่มเรียกใช้ฟังก์ชัน func ถ้า (หมดเวลา) หมดเวลา = settimeout (ในภายหลังรอ); if (callnow) {result = func.apply (บริบท, args); บริบท = args = null; } ผลตอบแทนผลลัพธ์; -ฉันคิดว่าสิ่งที่ยอดเยี่ยมเกี่ยวกับการใช้งาน _.debounce คือการเริ่มต้นตัวจับเวลาซ้ำอีกครั้งแทนที่จะปรับการดำเนินการล่าช้าของการโทรหาฟังก์ชั่น func โดยเรียก ClearTimeOut
ด้านบนเป็นฟังก์ชั่นการเพิ่มประสิทธิภาพประสิทธิภาพของ JavaScript และฟังก์ชั่น debounce ที่บรรณาธิการแนะนำให้คุณ ฉันหวังว่ามันจะเป็นประโยชน์กับคุณ หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับคุณทันเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!