وظيفة SetTimeout من JavaScript لا تتصل
-
19-08-2019 - |
سؤال
يبدو أن وظيفة setTimeout تمنحني دائمًا. في الوقت الحالي ، لدي وظيفة متكررة (تستدعي نفسها من خلال setTimeOut) وتغيير ارتفاع العناصر.
يتم إرسال الوظيفة وسيطتين: العنصر المراد تغييره وهذا الحد الأقصى للارتفاع. الغرض من الوظيفة هو تكشف العنصر ، أو "الانزلاق لأسفل" بوتيرة ثابتة. أنا أدرك أنه من المحتمل أن أحل هذه المشكلة مع jQuery ، لكنني أحاول وظيفتي الخاصة.
function slide_down(element, max_height)
{
if(element.clientHeight < max_height)
{
var factor = 10;
var new_height = (element.clientHeight + factor >= max_height) ? max_height : (element.clientHeight + factor);
element.style.height = new_height + 'px';
var func_call = 'slide_down(' + element + ', ' + max_height + ');';
window.setTimeout(func_call, 10);
}
}
لقد اختبرت الوسائط عندما تسمى الوظيفة في البداية. تم تعيين Max_Height على 20 لأنه الارتفاع المطلوب (حصلت على هذه القيمة من .Scrollheight).
عند الانتهاء من الوظيفة ، أريد أن أتصل بها حتى يكون Max_Height ارتفاع العنصر. أفعل ذلك باستخدام مكالمة setTimeOut هذه:
var func_call = 'slide_down(' + element + ', ' + max_height + ');';
window.setTimeout(func_call, 10);
وهو لا يعمل. هذا يعمل:
var func_call = 'alert(1);';
window.setTimeout(func_call, 10);
لقد حاولت أيضًا وضع استدعاء الوظيفة مباشرة في عبارة setTimeout ، لا يزال لا يعمل.
لاحظ أن ارتفاع العنصر يغير التكرار الأول ، فإن الوظيفة لا تدعو نفسها أبدًا. لذلك يتم تعيين متغير العنصر بشكل صحيح ، واستخدمت ALERT () لعرض max_height وهو صحيح أيضًا.
alert(func_call);
تنبيهات هذا:
slide_down([object HTMLParagraphElement], 20);
المحلول
عندما تفعل هذا:
var func_call = 'slide_down(' + element + ', ' + max_height + ');';
أنت تقوم بتحويل العنصر إلى سلسلة ، لذلك ستبدو مهلة الخاصة بك
slide_down("[Object]", 100);
من الواضح أنه لن ينجح.
ما يجب عليك فعله هو إنشاء إغلاق - إنه معقد بعض الشيء ولكنك في الأساس تقوم بإنشاء وظيفة ، ولا يزال المتغير المحلي من الوظيفة القديمة متاحًا في الوظيفة الجديدة.
function slide_down(element, max_height)
{
if(element.clientHeight < max_height)
{
var factor = 10;
var new_height = (element.clientHeight + factor >= max_height) ? max_height : (element.clientHeight + factor);
element.style.height = new_height + 'px';
var func = function()
{
slide_down(element, max_height);
}
window.setTimeout(func, 10);
}
}
أيضا 10 قصيرة بعض الشيء لمهلة - أوصي باستخدام 50 كحد أدنى.
نصائح أخرى
بادئ ذي بدء ، هذا "الآن لدي وظيفة متكررة (يدعو نفسها من خلال settimeout)" صراخ " setInterval بالنسبة لي إذا لم تكن تختلف هذه الفترة.
ثانياً ، هذا لأن مرجع العنصر يتم فقدانه في سلسلة Concat as element.toString () سيكون [كائن]. حاول تمرير معرف يمكنك إعادة العثور عليه ، أو تخزين مستوى أعلى ، أو (كما رأيت للتو Matt B يشير إلى) نموذج الطريقة الموسعة.
طريقة أكثر دقة لكتابة الطريقة (كامتداد إلى إجابة Gregs):
function slide_down(element, max_height)
{
if(element.clientHeight < max_height)
{ return; }
var factor = 10,
new_height = element.clientHeight + factor,
f = arguments.callee;
if( new_height > max_height )
{ new_height = max_height; }
element.style.height = new_height + 'px';
window.setTimeout(function() { f(element, max_height); }, 10);
}
الميزة الحقيقية لهذا الرمز العينة هي استخدام arguments.callee
. وبهذه الطريقة ، لن تكسر وظيفتك ، إذا قررت إعادة تسميتها. أنا أيضا ببساطة new_height
تعيين القيمة. المشكلة في الكود القديم هي أنك قمت بها element.clientHeight + factor
مرتين ، وهو نوع نوعا ما. لا يكون له أي تأثير ملحوظ على أدائك في هذه الحالة. ولكن من الجيد دائمًا تجنب حساب نفس الأشياء مرارًا وتكرارًا ، ولكن فقط قم بتخزين النتيجة للاستخدام لاحقًا.
I had a similar experience. When you are passing element the next time through, it is getting converted to a string in the function call, so when the function runs, it tries to find an element named [object].string or something, instead of what you intended.
Try changing your function parameter to take the id of the element and do a document.getElementById() call first thing inside the function.
The problem with your code is that you are fail to pass element parameter.
Instead of:
var func_call = 'slide_down(' + element + ', ' + max_height + ');'; window.setTimeout(func_call, 10);
try using anonymous function:
window.setTimeout(function() { slide_down(element, max_height) }, 10);
@matt.b: arguments passing into setTimeout call (the way you do) is not supported in IE.
Two things:
1. There is an alternate way to call setTimeout()
in which you pass the function and parameters, rather than a string to execute. In fact, the Gecko DOM manual states that your version of calling setTimeout()
is not recommended.
Instead of:
var func_call = 'slide_down(' + element + ', ' + max_height + ');';
window.setTimeout(func_call, 10);
Try this instead:
window.setTimeout(slide_down, 10, element, max_height);
Update: as RoBorg mentioned, this may not work in IE, so you might as well ignore it.
2. I have a feeling that calling setTimeout()
from within a function that was called itself by setTimeout()
is either not allowed or does not work well. I assume that you are chaining the calls like this because you want the code to execute repeatedly? If so, that is what window.setInterval()
is for.