شرح Debounce - كيفية جعل JavaScript الخاص بك ينتظر حتى ينتهي المستخدم من الكتابة

وظائف Debounce في JavaScript هي وظائف ذات ترتيب أعلى تحد من معدل استدعاء وظيفة أخرى.

دالة الترتيب الأعلى هي وظيفة تأخذ وظيفة كوسيطة أو تُرجع دالة كجزء من بيان الإرجاع الخاص بها. تعمل وظيفة debounce على حد سواء.

حالة الاستخدام الأكثر شيوعًا للارتداد هي تمريره كوسيطة لمستمع حدث مرتبط بعنصر HTML. للحصول على فهم أفضل لشكل هذا ، ولماذا يكون مفيدًا ، دعنا نلقي نظرة على مثال.

لنفترض أن لديك وظيفة مسماة myFuncيتم استدعاؤها في كل مرة تكتب شيئًا ما في حقل الإدخال. بعد الاطلاع على متطلبات مشروعك ، قررت أنك تريد تغيير التجربة.

بدلاً من ذلك ، تريد myFuncالتنفيذ عند مرور ثانيتين على الأقل منذ آخر مرة كتبت فيها شيئًا.

هذا هو المكان الذي يمكن أن يلعب فيه السقوط. بدلاً من الانتقال myFuncإلى مستمع الحدث ، ستمرر في الخصم. سيأخذ الخصم نفسه myFuncكوسيطة ، إلى جانب الرقم 2000.

الآن ، عند النقر فوق الزر ، myFuncسيتم التنفيذ فقط إذا انقضت ثانيتان على الأقل قبل الاتصال بآخر مرة myFunc.

كيفية تنفيذ وظيفة debounce

من البداية إلى النهاية ، لا يتطلب الأمر سوى 7 أسطر من التعليمات البرمجية لتنفيذ وظيفة debounce. يركز الجزء المتبقي من هذا القسم على تلك الأسطر السبعة من التعليمات البرمجية حتى نتمكن من رؤية كيفية عمل وظيفة debounce داخليًا.

function debounce( callback, delay ) { let timeout; return function() { clearTimeout( timeout ); timeout = setTimeout( callback, delay ); } }

بدءًا من السطر 1 ، أعلنا عن وظيفة جديدة باسم debounce. هذه الوظيفة الجديدة لها معلمتان ، callbackو delay.

function debounce( callback, delay ) { } 

callback هي أي وظيفة تحتاج إلى تحديد عدد مرات تنفيذها.

delayهو الوقت (بالمللي ثانية) الذي يجب أن ينقضي قبل callbackأن يتم تنفيذه مرة أخرى.

function debounce( callback, delay ) { let timeout; }

في السطر 2 ، نعلن عن متغير غير مهيأ اسمه timeout.

يحتفظ هذا المتغير الجديد بالعائد timeoutIDعندما نستدعي setTimeoutلاحقًا في debounceوظيفتنا.

function debounce( callback, delay ) { let timeout; return function() { } }

في السطر 3 ، نعيد دالة مجهولة. سيتم إغلاق هذه الوظيفة المجهولة فوق timeoutالمتغير حتى نتمكن من الاحتفاظ بالوصول إليها حتى بعد debounceانتهاء تنفيذ الاستدعاء الأولي .

يحدث الإغلاق في JavaScript عندما تحتفظ دالة داخلية بالوصول إلى النطاق المعجمي لوظيفتها الخارجية ، على الرغم من انتهاء تنفيذ الوظيفة الخارجية. إذا كنت تريد معرفة المزيد عن عمليات الإغلاق ، فيمكنك قراءة الفصل السابع من "You Don't Know JS" بقلم كايل سيمبسون
function debounce( callback, delay ) { let timeout; return function() { clearTimeout( timeout ); } }

في السطر 4 ، نسمي clearTimeoutطريقة WindowOrWorkerGlobalScopeالخلط. سيؤدي هذا إلى التأكد من أنه في كل مرة نقوم فيها باستدعاء debounceوظيفتنا ، timeoutيتم إعادة تعيينها ، ويمكن أن يبدأ العداد مرة أخرى.

و WindowOrWorkerGlobalScopemixin جافا سكريبت يتيح لنا الوصول إلى عدد قليل من الطرق المعروفة، مثل setTimeout، clearTimeout، setInterval، clearInterval، و fetch.

يمكنك معرفة المزيد عنها من خلال قراءة هذا المقال.

function debounce( callback, delay ) { let timeout; return function() { clearTimeout( timeout ); timeout = setTimeout( callback, delay ); } }

في السطر 5 ، وصلنا إلى نهاية debounceتنفيذ الوظيفة.

هذا السطر من التعليمات البرمجية يفعل بعض الأشياء. الإجراء الأول هو تعيين قيمة timeoutللمتغير الذي أعلنا عنه في السطر 2. القيمة هي timeoutIDالتي يتم إرجاعها عندما نطلبها setTimeout. سيسمح لنا ذلك بالإشارة إلى المهلة التي تم إنشاؤها عن طريق الاتصال setTimeoutحتى نتمكن من إعادة تعيينها في كل مرة debounceيتم فيها استخدام وظيفتنا.

الإجراء الثاني الذي تم تنفيذه هو الاتصال setTimeout. سيؤدي هذا إلى إنشاء مهلة سيتم تنفيذها callback(تم تمرير وسيطة الوظيفة إلى debounceوظيفتنا) بمجرد انقضاء delay(وسيطة الرقم التي تم تمريرها إلى debounceوظيفتنا).

نظرًا لأننا نستخدم المهلة ، callbackفلن يتم تنفيذها إلا إذا سمحنا لها بالوصول إلى 0. هذا هو المكان الذي debounceيلعب فيه قلب وظيفتنا نظرًا لأننا نعيد تعيين المهلة في كل مرة debounceيتم الاتصال بها. هذا ما يسمح لنا بالحد من معدل تنفيذ myFunc.

يحتوي السطران 5 و 6 على أقواس فقط ، لذلك لن نتجاوزهما.

هذا هو. هذه هي الطريقة التي debounceتعمل بها وظيفتنا داخليًا. الآن دعنا نضيف إلى مثالنا السابق من البداية. سنقوم بإنشاء حقل إدخال وإرفاق مستمع الحدث بوظيفتنا debounceكأحد وسائطه.

مثال العالم الحقيقي

أولاً ، نحتاج إلى إنشاء حقل إدخال.

Type something in! 

بعد ذلك ، نحتاج إلى إنشاء وظيفة نريد تنفيذها عندما نكتب شيئًا ما في حقل الإدخال.

function helloWorld() { console.log("Hello World!") }

أخيرًا ، نحتاج إلى تحديد حقل الإدخال الذي أنشأناه أعلاه وإرفاق keyupمستمع الحدث به.

const myInput = document.getElementById("myInput"); myInput.addEventListener( "keyup", debounce( helloWorld, 2000 ) );

هذا يختتم مثالنا في العالم الحقيقي! في كل مرة نكتب شيئًا في حقل الإدخال الخاص بنا ، helloWorldسيتم تنفيذه إذا مرت ثانيتان على الأقل منذ آخر مرة كتبنا فيها شيئًا.

شكر خاص لطبقية مستخدم Reddit للمساعدة في إصلاح بعض الكود الأولي في هذه المقالة. إليك عرض توضيحي عملي قام بإنشائه لهذه debounceالوظيفة على Repl.it.

ملاحظات ختامية

وظائف Debounce هي وظائف بسيطة لكنها قوية يمكن أن يكون لها تأثير ملحوظ على معظم تطبيقات JavaScript.

بينما كان مثالنا ممتعًا ومباشرًا ، تستخدم العديد من المؤسسات الكبيرة وظائف debounce لزيادة أداء تطبيقاتها.

إذا كنت تريد معرفة المزيد حول JavaScript ، فتحقق من موقع الويب الخاص بي! أنا أعمل على بعض الأشياء الرائعة في //juanmvega.com.