setTimeout یک تابع جاوا اسکریپت بومی است (اگرچه می توان با کتابخانه ای مانند jQuery از آن استفاده کرد ، همانطور که بعداً خواهیم دید) ، که یک عملکرد را فراخوانی می کند یا قطعه کد را پس از تأخیر مشخص (در میلی ثانیه) اجرا می کند. این ممکن است مفید باشد اگر به عنوان مثال ، شما بخواهید پس از مرور بازدید کننده برای مدت زمان مشخصی در صفحه خود ، یک پنجره بازشو نمایش دهید ، یا اگر قبل از حذف اثر شناور از یک عنصر ، تأخیر کوتاهی می خواهید (درصورت تصادفی کاربر moused)

set_timeout_2-01

این مقاله محبوب در سال 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 (یا هر چیز دیگری ، واقعاً) ، پس لطفاً به آدرس مراجعه کنید انجمن های سایت پوینت جایی که ما خوشحال خواهیم شد که به شما کمک کنیم