اذهب إلى المحتوى

السؤال

نشر (معدل)
for ( i=0 ;i<5 ;i++)  {
  setTimeout(function(){
    console.log ('hi');
  } , 3000);
}

عندي استفسار من بعد اذنكون.

ليش بهي الحالة setTimeout ما بتنطر 3 ثانية قبل طباعة hi في كل مرة.

شكرا.

تم التعديل في بواسطة Mustafa Suleiman
تعديل عنوان السؤال

Recommended Posts

  • 0
نشر

أنت تقوم بالتكرار 5 مرات، في كل مرة هو سيقوم بوضع ال timeout و الانتقال إلى التكرار التالي، و بالتالي يمكنك أن تتخيل أنك تضع timeout بمقدار 3 ثانية و لكن الكل يبدأ تقريبا في نفس الوقت.

أي أنه لا ينتظر في التابع timeout و يوقف التنفيذ، فقط يضع ما تريد تنفيذه و يكمل تنفيذه.

يمكنك القيام بما تريد عن طريق تشغيل تكرار كل مدة زمنية و إطفاءه بعد نهاية المدة، كما يلي:

let interval = 3000;
let totalInterval = 5 * interval;

function startTimer() {
    let myTimer = setInterval(function f() {
        console.log('hi');
    }, interval);

    setTimeout(function f() {
        clearInterval(myTimer);
    }, totalInterval);
}

startTimer();

 

  • 0
نشر

السبب الأساسي هو طريقة عمل دالة setTimeout في جافا سكريبت.

فعند تنفيذ الحلقة for، يتم تكرار دالة setTimeout في كل تكرار بحيث تقوم بتعيين دالة لتنفيذها بعد فترة زمنية محددة، وهي 3 ثوانٍ في الكود.

ولكن، تكون قيمة i قد اكتمل تنفيذها قبل أن تنفذ دالة setTimeout المعطاة، مما يعني أن جميع تكرارات الحلقة for ستكون قد اكتملت بسرعة في غضون فترة زمنية صغيرة، بحيث تكون قيمة i قد وصلت إلى القيمة 5.

وعندما يحين الوقت لتنفيذ الدوال التي تم تعيينها في setTimeout، فإن قيمة i الحالية هي القيمة الأخيرة (5) في كل حالة، وبالتالي، سيتم طباعة "hi" خمس مرات في الوقت نفسه بعد انتهاء فترة الانتظار البالغة 3 ثوانٍ.

والصحيح هو كتابة الكود كالتالي بوضع قيمة إنتظار  بناءًا على قيمة i:

for (let i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log('hi: ' + i );
  }, 1000 * (i + 1));
}

 

  • 0
نشر

مشكلة في الكود الذي قدمته. حدث setTimeout يجدد دائمًا المؤقت بعد مرور 3 ثوانٍ، ولذلك يقوم بتكرار طباعة "hi" في كل مرة بعد انتهاء المؤقت السابق. ومع ذلك، في هذا الحالة، فإن جميع المؤقتات تم تعيينها لتنتهي بعد 3 ثوانٍ، ولذلك يتم طباعة "hi" في النهاية بعد مرور 3 ثوانٍ من البداية.

إذا كنت ترغب في طباعة "hi" كل 3 ثوانٍ، يمكنك استخدام setInterval بدلاً من setTimeout. هناك فرق بين الاثنين، حيث يكرر setInterval الوظيفة بشكل متكرر كل فترة زمنية محددة، بينما ينفذ setTimeout الوظيفة مرة واحدة فقط بعد انتهاء المؤقت الزمني.

يمكنك تحقيق ذلك باستخدام الكود التالي:

var i = 0;
var intervalId = setInterval(function() {
  console.log('hi');
  i++;
  if (i === 5) {
    clearInterval(intervalId);
  }
}, 3000);

في هذا الكود، يتم طباعة "hi" كل 3 ثوانٍ باستخدام setInterval، ويتم التحكم في عدد المرات التي يتم فيها طباعة "hi" باستخدام المتغير i وشرط if. عندما يصبح i يساوي 5، يتم استدعاء clearInterval لإيقاف تنفيذ الوظيفة وإلغاء المؤقت.

  • 0
نشر

هناك طريقة أخرى لتجنب هذا السلوك وهي باستخدام Promise و async/await. يمكن استخدام Promise لتنفيذ الكود بعد فترة زمنية محددة بدلاً من setTimeout، ويمكن استخدام async/await لتجنب تنفيذ الأكواد المحددة في Promise في نفس الوقت.

مثال على استخدام Promise و async/await:

function delay(time) {
  return new Promise((resolve) => {
    setTimeout(resolve, time);
  });
}

async function printHi() {
  for (let i = 0; i < 5; i++) {
    await delay(3000);
    console.log('hi');
  }
}

printHi();

في هذا المثال، تم استخدام دالة delay لإنشاء Promise لتأخير تنفيذ الكود بعد فترة زمنية محددة (3 ثوانٍ)، وتم استخدام الكلمة الرئيسية async مع الدالة printHi للسماح باستخدام await داخلها. ثم تم استخدام await داخل حلقة الـ for لتأخير تنفيذ الكود بعد فترة زمنية محددة، وبالتالي تم طباعة "hi" بشكل متتابع بعد فترة زمنية محددة لكل تأخير.

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...