setTimeout
یک تابع جاوا اسکریپت بومی است (اگرچه می توان با کتابخانه ای مانند jQuery از آن استفاده کرد ، همانطور که بعداً خواهیم دید) ، که یک عملکرد را فراخوانی می کند یا قطعه کد را پس از تأخیر مشخص (در میلی ثانیه) اجرا می کند. این ممکن است مفید باشد اگر به عنوان مثال ، شما بخواهید پس از مرور بازدید کننده برای مدت زمان مشخصی در صفحه خود ، یک پنجره بازشو نمایش دهید ، یا اگر قبل از حذف اثر شناور از یک عنصر ، تأخیر کوتاهی می خواهید (درصورت تصادفی کاربر moused)
این مقاله محبوب در سال 2020 به روز شده است.
مثال اصلی setTimeout
برای نشان دادن مفهوم ، نسخه ی نمایشی زیر ، دو ثانیه پس از کلیک دکمه ، یک پنجره بازشو نمایش می دهد.
قلم را ببینید تاخیر در حالت پنجره بازشو با شکوه توسط SitePoint (SitePoint) بر CodePen.
اگر پنجره بازشو را باز نمی بینید ، لطفاً بازدید کنید CodePen و نسخه ی نمایشی را در آنجا اجرا کنید.
نحو
از مستندات MDN، نحو برای setTimeout
به شرح زیر است:
var timeoutID = scope.setTimeout(function[, delay, arg1, arg2, ...]);
var timeoutID = scope.setTimeout(function[, delay]);
var timeoutID = scope.setTimeout(code[, delay]);
جایی که:
timeoutID
یک شناسه عددی است که می تواند همراه با آن استفاده شود clearTimeout برای لغو تایمر.scope
اشاره به رابط پنجره یا رابط WorkerGlobalScope.function
تابعی است که باید پس از انقضا تایمر اجرا شود.code
یک نحو جایگزین است که به شما امکان می دهد به جای تابع یک رشته را وارد کنید ، که با اتمام زمان سنج تایمر کامپایل و اجرا می شود.delay
تعداد میلی ثانیه است که در آن فراخوانی عملکرد باید به تأخیر بیفتد. در صورت حذف ، این به طور پیش فرض 0 است.arg1, ..., argN
آرگومان های اضافی منتقل شده به عملکرد مشخص شده توسطfunction
.
توجه: براکت های مربع []
پارامترهای اختیاری را نشان می دهد.
setTimeout در مقابل windows.setTimeout
متوجه خواهید شد که نحو فوق استفاده می کند scope.setTimeout
. چرا این هست؟
خوب ، هنگام اجرای کد در مرورگر ، scope
اشاره به جهانی است window
هدف – شی. هر دو setTimeout
و window.setTimeout
به همان عملکرد اشاره کنید ، تنها تفاوت در این است که در جمله دوم ما به آن اشاره می کنیم setTimeout
روش به عنوان یک ویژگی از window
هدف – شی.
به نظر من ، این پیچیدگی را برای سود کم یا هیچ سود اضافه می کند. اگر جایگزینی تعریف کرده اید setTimeout
روشی که در زنجیره دامنه با اولویت یافت و برگردانده می شود ، در این صورت احتمالاً مشکلات بزرگتری برای نگرانی دارید.
برای اهداف این آموزش ، من آن را حذف می کنم window
، اما در نهایت ، کدام نحو را انتخاب می کنید به خود شما بستگی دارد.
نمونه هایی از کاربرد
setTimeout
ارجاع به یک تابع را به عنوان اولین آرگومان می پذیرد.
این می تواند نام یک تابع باشد:
function greet(){
alert('Howdy!');
}
setTimeout(greet, 2000);
متغیری که به یک تابع (عبارت تابع) اشاره دارد:
const greet = function(){
alert('Howdy!');
};
setTimeout(greet, 2000);
یا یک تابع ناشناس:
setTimeout(() => { alert('Howdy!'); }, 2000);
همانطور که در بالا ذکر شد ، عبور نیز امکان پذیر است setTimeout
یک رشته کد برای اجرای آن:
setTimeout('alert("Howdy!");', 2000);
با این حال ، این به دلایل زیر توصیه نمی شود:
- خواندن آن دشوار است (و در نتیجه حفظ و یا اشکال زدایی آن سخت است).
- از ضمنی استفاده می کند
eval
، که یک خطر بالقوه امنیتی است. - این سرعت نسبت به گزینه های دیگر کندتر است ، زیرا مجبور به فراخوانی مفسر JS است.
این س Stال سرریز پشته اطلاعات بیشتری در مورد نکات فوق ارائه می دهد.
عبور پارامترها به setTimeout
در یک سناریو اساسی ، روش مرورگر متقابل برای انتقال پارامترها به یک پاسخ برگشتی که توسط آن اجرا می شود ، است setTimeout
با استفاده از یک تابع ناشناس به عنوان اولین آرگومان است.
در مثال زیر ، یک حیوان تصادفی را از یک انتخاب می کنیم animals
آرایه کنید و این حیوان تصادفی را به عنوان یک پارامتر به a منتقل کنید makeTalk
تابع. makeTalk
سپس تابع توسط setTimeout
با یک ثانیه تأخیر:
function makeTalk(animal){
const noises = {
cat: 'purr',
dog: 'woof',
cow: 'moo',
pig: 'oink',
}
console.log(`A ${animal} goes ${noises[animal]}.`);
}
function getRandom (arr) {
return arr[Math.floor(Math.random()*arr.length)];
}
const animals = ['cat', 'dog', 'cow', 'pig'];
const randomAnimal = getRandom(animals);
setTimeout(() => {
makeTalk(randomAnimal);
}, 1000);
توجه: من از یک عملکرد منظم استفاده کرده ام (getRandom
) برای بازگرداندن یک عنصر تصادفی از یک آرایه. نوشتن این به عنوان یک عبارت تابع با استفاده از یک تابع arrow نیز ممکن است:
const getRandom = arr => arr[Math.floor(Math.random()*arr.length)];
در بخش بعدی به توابع پیکان خواهیم رسید.
یک روش جایگزین
همانطور که از نحو بالای مقاله مشاهده می شود ، روش دوم برای انتقال پارامترها به یک تماس برگشتی اجرا شده توسط وجود دارد setTimeout
. این شامل لیست پارامترهای بعد از تأخیر است.
با اشاره به مثال قبلی ، این به ما می دهد:
setTimeout(makeTalk, 1000, randomAnimal);
متأسفانه ، این در IE9 یا پایین ، جایی که پارامترها از آنجا می آیند ، کار نمی کند undefined
. اگر در موقعیت غیرقابل پیش بینی هستید که مجبور به پشتیبانی از IE9 هستید ، این مسئله وجود دارد یک پلی پرک موجود در MDN.
مشکل با this
کد اجرا شده توسط setTimeout
در چارچوب اجرای جداگانه ای برای عملکردی که از آن فراخوانی شده است اجرا می شود. وقتی زمینه از this
کلمه کلیدی مهم است:
const dog = {
sound: 'woof',
bark() {
console.log(`Rover says ${this.sound}!`);
}
};
dog.bark();
setTimeout(dog.bark, 50);
دلیل این خروجی این است که ، در مثال اول ، this
اشاره به dog
شی ، در حالی که در مثال دوم this
به جهانی اشاره می کند window
شی (که a ندارد sound
ویژگی).
برای مقابله با این مشکل ، اقدامات مختلفی وجود دارد …
صریحاً مقدار را تعیین کنید this
با استفاده از می توانید این کار را انجام دهید بستن، روشی که عملکرد جدیدی را ایجاد می کند که وقتی فراخوانی می شود دارای ویژگی خاص خود است this
کلمه کلیدی به مقدار ارائه شده تنظیم شده است (در مورد ما ، dog
هدف – شی). این به ما می دهد:
setTimeout(dog.bark.bind(dog), 50);
توجه داشته باشید: bind
در ECMAScript 5 معرفی شد ، بنابراین فقط در کار خواهد کرد مرورگرهای مدرن تر. می توانید در مورد آن بیشتر بخوانید (و روشهای دیگر تعیین مقدار this
) در این مقاله SitePoint.
از کتابخانه استفاده کنید
بسیاری از کتابخانه ها برای حل این مسئله توابع داخلی دارند. به عنوان مثال ، jQuery’s jQuery.proxy () روش. این یک عملکرد را می گیرد و یک عملکرد جدید را برمی گرداند که همیشه یک زمینه خاص دارد. در مورد ما ، این موارد عبارتند از:
setTimeout($.proxy(dog.bark, dog), 50);
استفاده از توابع Arrow با setTimeout
توابع پیکان با ES6 معرفی شدند. نحو آنها بسیار کوتاه تر از یک تابع معمولی است:
(param1, param2, paramN) => expression
البته می توانید از آنها استفاده کنید setTimeout
، اما یک گفتار وجود دارد که باید از آن آگاه باشید – یعنی عملکردهای پیکان خاص خودشان نیستند this
مقدار. در عوض ، آنها از this
ارزش متن لغوی محصور.
با استفاده از یک عملکرد منظم:
const dog = {
sound: 'woof',
bark() {
console.log(`Rover says ${this.sound}!`);
}
};
dog.bark();
استفاده از عملکرد پیکان:
const dog = {
sound: 'woof',
bark: () => {
console.log(`Rover says ${this.sound}!`);
}
};
dog.bark();
در مثال دوم ، this
به جهانی اشاره می کند window
شی (که دوباره ، a ندارد sound
ویژگی).
این می تواند ما را در هنگام استفاده از توابع arrow با بالا ببرد setTimeout
. قبلاً می دیدیم که چگونه می توان تابعی را به نام a تأمین کرد setTimeout
با صحیح this
مقدار:
setTimeout(dog.bark.bind(dog), 50);
این هنگام استفاده از یک عملکرد پیکان در introduce
روش ، زیرا عملکرد پیکان خاص خود را ندارد this
مقدار. روش هنوز ثبت خواهد شد undefined
.
کد تمیز کننده با توابع پیکان و setTimeout
با این حال ، زیرا توابع پیکان خاص خود را ندارند this
ارزش ، همچنین می تواند به نفع ما کار کند.
کد را مانند این در نظر بگیرید:
const dog = {
sound: 'woof',
delayedBark() {
setTimeout(
function() {
console.log(`Rover says ${this.sound}!`);
}
.bind(this)
, 1000);
}
}
dog.delayedBark();
با یک تابع arrow می توان آن را به طور خلاصه دوباره نوشت:
const dog = {
sound: 'woof',
delayedBark() {
setTimeout(
() => { console.log(`Rover says ${this.sound}!`); }, 1000
);
}
}
dog.delayedBark();
اگر می خواهید یک آغازگر در مورد عملکردهای پیکان داشته باشید ، لطفاً “توابع پیکان ES6: نحو چاق و مختصر در JavaScript” را بخوانید.
لغو تایمر
همانطور که در ابتدای مقاله آموختیم ، مقدار بازگشتی از setTimeout
یک شناسه عددی است که می تواند برای لغو تایمر همراه با clearTimeout
تابع:
const timer = setTimeout(myFunction, 3000);
clearTimeout(timer);
بیایید این را عملی ببینیم. در قلم زیر ، اگر روی آن کلیک کنید شمارش معکوس را شروع کنید دکمه ، شمارش معکوس آغاز می شود. اگر شمارش معکوس کامل شود ، بچه گربه ها آن را دریافت می کنند. اما اگر دکمه را فشار دهید شمارش معکوس را متوقف کنید دکمه ، تایمر متوقف شده و تنظیم مجدد می شود. (اگر وقتی شمارش معکوس به صفر می رسد ، جلوه جالبی نمی بینید ، قلم را دوباره با استفاده از دکمه پایین سمت راست تعبیه کنید.
قلم را ببینید بچه گربه های SetTimeout توسط SitePoint (SitePoint) بر CodePen.
بسته بندی کردن
یکی از هشدارهای احتمالی که باید از آن آگاه شد این واقعیت است که setTimeout
ناهمزمان است این مرجع عملکردی را که دریافت می کند صف می کشد تا پس از پایان اجرای پشته تماس فعلی ، اجرا شود. با این وجود ، همزمان یا روی یک موضوع جداگانه (به دلیل تک رشته بودن جاوا اسکریپت) اجرا نمی شود.
console.log(1);
setTimeout(() => { console.log(2); }, 0);
console.log(3);
اگرچه ما تماس می گیریم setTimeout
با تاخیر صفر ثانیه ، شماره ها هنوز از حالت منظم خارج می شوند. این به این دلیل است که چه زمانی setTimeout
تایمر منقضی شده است ، موتور جاوا اسکریپت عملکرد پاسخ خود را در یک صف قرار می دهد ، پشت دیگری console.log
اظهارات ، اجرا شود.
اگر می خواهید در مورد آنچه که هنگام اجرای JavaScript اتفاق می افتد بیشتر بدانید ، من این فیلم را از JSConf 2014 بسیار توصیه می کنم: به هر حال حلقه رویداد چیست؟
درخواستAnimationFrame ()
همچنین باید از آن آگاه باشید درخواستAnimationFrame. این روش به مرورگر می گوید که شما می خواهید قبل از رنگ آمیزی بعدی یک عملکرد مشخص را فراخوانی کنید.
هنگام ساخت انیمیشن ، باید طرفدار آن باشیم requestAnimationFrame
بیش از استفاده setTimeout
، زیرا تقریباً شصت بار در ثانیه شلیک می کند ، برخلاف آن setTimeout
، که پس از حداقل فراخوانی می شود n
میلی ثانیه با استفاده از requestAnimationFrame
ما می توانیم از تغییر چیزی بین دو بار به روزرسانی قاب جلوگیری کنیم.
در اینجا مثالی از نحوه استفاده آورده شده است requestAnimationFrame
متحرک کردن a div
عنصر در سراسر صفحه:
const div = document.querySelector('#rectangle');
let leftPos = 0;
function animateDiv(){
leftPos += 1;
div.style.left = `${leftPos}px`;
if (leftPos < 100) requestAnimationFrame(animateDiv);
}
requestAnimationFrame(animateDiv);
البته با استفاده از آن می توانید به همان چیز دست پیدا کنید setTimeout
:
const div = document.querySelector('#rectangle');
let leftPos = 0;
function animateDiv(){
leftPos += 1;
div.style.left = `${leftPos}px`;
if (leftPos < 100) setTimeout(animateDiv, 1000/60);
}
animateDiv();
اما همانطور که گفته شد ، استفاده از requestAnimationFrame
مزایای مختلفی از جمله اجازه دادن به بهینه سازی مرورگر و توقف انیمیشن در برگه های غیرفعال را ارائه می دهد.
قلم را ببینید
انیمیشن با درخواست AnimationFrame توسط SitePoint (SitePoint)
بر CodePen.
jQuery.delay ()
در آخر ، من می خواهم هرگونه سردرگمی بین استفاده از JavaScript بومی را برطرف کنم setTimeout
عملکرد و روش تأخیر جی کوئری.
delay
روش به طور خاص برای اضافه کردن تاخیر بین روش ها در یک صف جی کوئری مشخص است. امکان لغو تأخیر وجود ندارد. به عنوان مثال ، اگر می خواهید یک تصویر را برای یک ثانیه محو کنید ، برای مدت پنج ثانیه آن را مشاهده کنید و سپس آن را برای مدت زمان یک ثانیه محو کنید ، می توانید موارد زیر را انجام دهید:
$('img').fadeIn(1000).delay(5000).fadeOut(1000);
setTimeout
بهتر است برای هر چیز دیگری استفاده شود.
توجه: اگر پس از تأخیر مشخص نیاز به اجرای مکرر کد دارید ، پس setInterval
بیشتر مناسب کار است. تو میتوانی بخوانی اطلاعات بیشتر در مورد این عملکرد در اینجا.
نتیجه
در این مقاله ، من نحوه استفاده را نشان داده ام setTimeout
برای به تأخیر انداختن اجرای یک تابع. من همچنین نشان داده ام که چگونه پارامترها را به آنها منتقل کنیم setTimeout
، حفظ this
مقدار داخل پاسخگویی آن و همچنین نحوه لغو تایمر.
اگر درمورد استفاده از مشکلی در کدگذاری پیدا کردید setTimeout
(یا هر چیز دیگری ، واقعاً) ، پس لطفاً به آدرس مراجعه کنید انجمن های سایت پوینت جایی که ما خوشحال خواهیم شد که به شما کمک کنیم