إن خنق الوظيفة ، ببساطة ، يجعل وظيفة غير قادرة على أن تسمى بشكل مستمر خلال فترة زمنية قصيرة جدًا. فقط عندما يتم تنفيذ الوظيفة الأخيرة بعد الفاصل الزمني المحدد من خلاله ، يمكن إجراء المكالمة التالية للوظيفة.
مبدأ خنق الوظيفة بسيط للغاية. أعتقد أن الجميع قد فكروا في الأمر ، وهذا هو المؤقت. عندما أقوم بإعداد وقت ، قام أولاً بتأخير الحدث لفترة من الوقت قبل التنفيذ. إذا تم تشغيل الحدث مرة أخرى خلال هذه الفاصل الزمني ، فإننا نقوم بمسح المؤقت الأصلي ثم SetTimeOut مؤقتًا جديدًا لتأخير التنفيذ لفترة من الوقت ، هذا كل شيء.
في السيناريوهات التالية ، غالبًا ما تؤدي السيناريوهات التالية سلوكيات ثقيلة مثل عمليات DOM وتحميل الموارد ، مما يؤدي إلى توقف واجهة المستخدم أو حتى حوادث المتصفح.
1. تغيير حجم الأحداث وتمريرها من كائن النافذة
2. حدث Mousemove أثناء السحب
3. أحداث موسى و Keydown
4. أحداث keyup التي يتم إكمالها تلقائيًا عن طريق إدخال النص
في الواقع ، بالنسبة لحدث تغيير حجم النافذة ، فإن المتطلبات الفعلية هي التوقف عن تغيير حجم N -milliseconds وأداء المعالجة اللاحقة ؛ في حين أن معظم الأحداث الأخرى تتطلب معالجة لاحقة بتردد معين. هناك حلان لهذين الاحتياجتين ، Debonce و Throttle.
Throttle و Debounce هما حلان لحل مشكلة عدم تطابق الطلب وسرعة الاستجابة. الفرق بين الاثنين يكمن في اختيار استراتيجيات مختلفة.
تنفيذ وظائف على فترات مثل الخانق.
إذا تم تشغيل الحدث مرة أخرى داخل الفاصل الزمني D-Debounce ، فسيتم إعادة توقيت الموقت حتى يصبح وقت التوقف أكبر من أو يساوي T.
1. التنفيذ البسيط لوظيفة الخانق
وظيفة الخانق (FN ، عتبة ، نطاق) {threshhold || (Threshhold = 250) ؛ var last ، timer ؛ عودة وظيفة () {var context = Scope || هذا؛ var now = +new date () ، args = mations ؛ if (last && now - last + threshhold <0) {// تمسك به clearTimeOut (defertimer) ؛ timer = setTimeOut (function () {last = now ؛ fn.apply (context ، args) ؛} ، threshhold) ؛ } آخر {last = now ؛ fn.apply (السياق ، args) ؛ }} ؛}طرق الاتصال
$ ('body'). on ('mousemove' ، Throttle (function (event) {console.log ('tick') ؛} ، 1000)) ؛2. التنفيذ البسيط لوظيفة Debounce
دالة debounce (fn ، التأخير) {var timer = null ؛ function function () {var context = this ، args = mations ؛ ClearTimeout (مؤقت) ؛ timer = setTimeOut (function () {fn.apply (السياق ، args) ؛} ، التأخير) ؛ } ؛}طرق الاتصال
$ ('input.username'). keypress (debounce (function (event) {// do the Ajax request} ، 250)) ؛3. تنفيذ التغليف البسيط
/** * Throttle * param fn ، انتظر ، debounce */var throttle = function (fn ، wait ، debounce) {var timer = null ، // timer t_last = null ، // last time set ، // context args ، // parmeter diff ؛ // اختلاف الوقت إرجاع funciton () {var curr = + new date () ؛ var context = هذا ، args = الوسيطات ؛ ClearTimeout (مؤقت) ؛ if (debounce) {// إذا كان debounce timer = setTimeOut (function () {fn.apply (context ، args) ؛} ، انتظر) ؛ } آخر {// إذا كان خنقًا إذا (! t_last) t_last = curr ؛ if (curr - t_last> = wait) {fn.apply (السياق ، انتظر) ؛ السياق = الانتظار = فارغ ؛ }} سترملخص: هاتان الطريقتان مناسبة لبعض الأحداث التي سيتم تشغيلها مرارًا وتكرارًا ، مثل: Mousemove ، Keydown ، Keyup ، keypress ، التمرير ، إلخ.
إذا قمت بربط الأحداث الأصلية فقط ولم تتحكم فيها ، فسيتم تعثر المتصفح وستكون تجربة المستخدم سيئة. من أجل تحسين أداء JS ، يوصى باستخدام اختناق الوظيفة أو الدعامة الدائرية للتحكم عند استخدام الأحداث المذكورة أعلاه والأحداث المماثلة.
4. تحليل رمز المصدر المتعلق بـ Swefcore v1.7.0
1. _.throttle وظيفة
_. var timeout = null ؛ // timer var previour = 0 ؛ // آخر مرة أدت إلى أن (خيارات) خيارات = {} ؛ var later = function () {previce = Options.Leading === false؟ 0: _.now () ؛ مهلة = فارغة ؛ النتيجة = func.apply (السياق ، args) ؛ إذا (! مهلة) سياق = args = null ؛ } ؛ Return Function () {var now = _.now () ؛ // ما إذا كان يجب تنفيذ (! السابق && options.leading === false) سابق = الآن ؛ // هنا مفهوم للبقاء: كم من الوقت المتبقي لتنفيذ الحدث var المتبقي = الانتظار - (الآن - سابق) ؛ السياق = هذا ؛ args = الحجج ؛ // المتبقية <= 0 بالنظر إلى أنه يتم إعادة محاكمة الحدث بعد إيقاف الحدث أو // عندما يكون الانتظار مختلفًا تمامًا ، سيتم تشغيل الحدث على الفور // يبقى> لا يأخذ الانتظار في الاعتبار السيناريو المقابل // الآن هو أمر موجود دائمًا ، فهو لا يتم توجيهه على الفور (سيظل ذلك هو الموقف دائمًا (سيؤمن ذلك) ||. مهلة = فارغة ؛ } السابق = الآن ؛ النتيجة = func.apply (السياق ، args) ؛ إذا (! مهلة) سياق = args = null ؛ // ما إذا كان يجب تتبع} آخر إذا (! timeout && options.trailing! == false) {timeout = setTimeout (لاحقًا ، تبقى) ؛ } نتيجة الإرجاع ؛ } ؛} ؛كما يتضح من ما سبق ، نظرت في المواقف المزيد من المواقف: الخيارات.
يتم تنفيذ المرة الأولى ، الافتراضي صحيح ، مما يعني أنه سيتم تنفيذ المرة الأولى. أول مرة يتم فيها تعطيل خيارات التنفيذ. يتم تمرير آخر مرة {trameing: false} تعني أنه لم يتم تنفيذ آخر مرة. ما يسمى المرة الأولى هو ما إذا كان الحدث قد تم تنفيذه أولاً. عندما يبدأ الحدث للتو ، ما إذا كان ينبغي تشغيل الحدث أولاً. إذا كنت تريد ، السابق = 0 ، والبقاء سلبيا ، ما يسمى آخر مرة سواء تم تنفيذ الوظيفة ، يتم استدعاء على الفور بعد انتهاء الحدث. يتم تشغيل هذه الطريقة في المرة الأخيرة. إذا كنت ترغب في التنفيذ ، يتم تعيين مؤقت ، أي ، يجب تنفيذه مرة واحدة بعد انتهاء الحدث. remianing> الانتظار يعني أنه تم تعديل وقت العميل.
2. _.debounce وظيفة
_. var لاحقًا = function () {// عندما يتم إرجاع الوظيفة التي يتم إرجاعها بواسطة _.debounce عدة مرات خلال الفاصل الزمني المحدد عن طريق الانتظار ، سيتم تحديث قيمة الطابع الزمني بشكل مستمر ، مما يؤدي إلى آخر <Wait && last> = 0 دائمًا صحيح ، وبالتالي البدء باستمرار في مؤقت جديد لتنفيذ التأخير ، var last = _now () - timestamp ؛ if (last <wait && last> = 0) {timeout = setTimeOut (لاحقًا ، انتظر - last) ؛ } آخر {timeout = null ؛ if (! فوري) {result = func.apply (السياق ، args) ؛ إذا (! مهلة) سياق = args = null ؛ }}} ؛ الإرجاع دالة () {context = this ؛ args = الحجج ؛ الطابع الزمني = _.now () ؛ // عندما يتم استدعاء الطريقة لأول مرة وبعد الفاصل الزمني المحدد عن طريق الانتظار ، بدأ الموقت في استدعاء وظيفة FUNC إذا (! timeout) timeout = setTimeout (لاحقًا ، انتظر) ؛ if (callNow) {result = func.apply (السياق ، args) ؛ السياق = args = null ؛ } نتيجة الإرجاع ؛ } ؛} ؛أعتقد أن الشيء الرائع في تنفيذ _.debounce هو بدء الموقت بشكل متكرر بدلاً من ضبط تنفيذ تأخير استدعاء وظائف FUNC عن طريق الاتصال ClearTimeout.
ما ورد أعلاه هو وظيفة تحسين أداء JavaScript و Debounce التي قدمها لك المحرر. آمل أن يكون ذلك مفيدًا لك. إذا كان لديك أي أسئلة ، فيرجى ترك رسالة لي وسوف يرد المحرر إليك في الوقت المناسب. شكرا جزيلا لدعمكم لموقع wulin.com!