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

كيف أجعل دالة غير متزامنة تنتظر دالة أخرى غير متزامنة في جافا سكريبت

مصطفى اوريك

السؤال

السلام عليكم

لدي الكود التالي:

const landingHeader = document.querySelector(".landing__header");
const landingParagraph = document.querySelector(".landing__paragraph");

const landingHeaderText = "Iam Mustapha";
const landingParagraphText = "Full Stack Developer";

async function textTypingEffect(element, text, i = 0, time) {
    if (i == text.length) {
        return;
    }

    element.textContent += text[i];

    setTimeout(() => {
        textTypingEffect(element, text, i + 1, time);
    }, time);

}

async function startTyping() {
    await textTypingEffect(landingHeader, landingHeaderText, 0, 35);
    textTypingEffect(landingParagraph, landingParagraphText, 0, 5);
}

startTyping();

أريد أن تشتغل الدالة textTypingEffect(landingParagraph, landingParagraphText, 0, 5) بعد أن تكتمل الدالة textTypingEffect(landingHeader, landingHeaderText, 0, 35) من التنفيذ, أي بعد أن يتحقق الشرط i == text.length

بالتالي بعد أن يتحقق هذا الشرط سوف تقوم الدالة بإرجاع Promise فارغ, وهذا من المفروض أن يجعل الدالة الثانية تعمل, لكن هذا لا يحدث, الدالتين تشتغلان في نفس الوقت

ما المشكلة؟

رابط هذا التعليق
شارك على الشبكات الإجتماعية

Recommended Posts

  • 1

وعليكم السلام ورحمة الله وبركاته.

المشكلة تكمن في كيفية تنظيم تنفيذ الدالة textTypingEffect بشكل غير متزامن. في الوقت الحالي، الدالة textTypingEffect تستخدم setTimeout لتأخير تنفيذ الدورة التالية من الطباعة بالنص، وهذا يسمح لكلا الدالتين بالعمل في نفس الوقت حيث أن setTimeout لا تحتاج إلى الإنتظار حيث يتم تنفيذها فعليا ولكن الدالة التي بداخلها هى التي تتأخر لذلك لا تنتظر الإنتهاء حتي تعمل.

لحل هذه المشكلة وجعل الدالة الثانية textTypingEffect على landingParagraph تنفذ بعد الانتهاء من الدالة الأولى textTypingEffect على landingHeader  يمكنك استخدام Promises بشكل صحيح للتحكم في تسلسل التنفيذ

في الدالة textTypingEffect نعدلها  لتعيد Promise بمجرد الانتهاء من الطباعة الكاملة :

function textTypingEffect(element, text, i = 0, time) {
    return new Promise(resolve => {
        if (i == text.length) {
            resolve();
            return;
        }

        element.textContent += text[i];

        setTimeout(() => {
            textTypingEffect(element, text, i + 1, time).then(resolve);
        }, time);
    });
}

هنا قمنا بإرجاع promise من الدالة textTypingEffect حتي يتم إنتظارها عند كتابة await textTypingEffect .

وبداخلها قمنا بكتابة resolve() إذا كان طول النص مثل i حتي يتم إنهاء ال promise عندما يتم طباعة جيمع الحروف.

وبدخل ال setTimeout قمنا بوضع  textTypingEffect(element, text, i + 1, time).then(resolve); أي في كل مرة نمرر دالة resolve التي سوف تنهي ال promise في جزء ال then .

ونعدل الدالة startTyping لتصبح كالتالي :

async function startTyping() {
    await textTypingEffect(landingHeader, landingHeaderText, 0, 35);
    await textTypingEffect(landingParagraph, landingParagraphText, 0, 5);
}

بهذه التعديلات الآن startTyping ستنتظر حتى يتم الانتهاء من textTypingEffect على landingHeader بفضل الـ await، ثم بعد ذلك ستبدأ في تنفيذ textTypingEffect على landingParagraph. هذا يضمن أنهما لن يتنافسا على التنفيذ في نفس الوقت وسيعملان بالتتابع كما هو متوقع.

وهذا هو الكود كاملا بعد التعديل :

const landingHeader = document.querySelector(".landing__header");
const landingParagraph = document.querySelector(".landing__paragraph");

const landingHeaderText = "Iam Mustapha";
const landingParagraphText = "Full Stack Developer";


function textTypingEffect(element, text, i = 0, time) {
    return new Promise(resolve => {
        if (i == text.length) {
            resolve(); 
            return;
        }

        element.textContent += text[i];

        setTimeout(() => {
            textTypingEffect(element, text, i + 1, time).then(resolve);
        }, time);
    });
}

async function startTyping() {
    await textTypingEffect(landingHeader, landingHeaderText, 0, 35);
    textTypingEffect(landingParagraph, landingParagraphText, 0, 5);
}

startTyping()

 

رابط هذا التعليق
شارك على الشبكات الإجتماعية

  • 0

من الأفضل الإعتماد على async/await لتجنب مثل تلك المشاكل، أي بدلاً من استخدام setTimeout بشكل متكرر داخل دالة textTypingEffect، تقوم باستخدام Promise واحدة فقط لكل نص ونستخدم await لانتظار مرور الوقت المحدد بين كل حرف.

const landingHeader = document.querySelector(".landing__header");
const landingParagraph = document.querySelector(".landing__paragraph");

const landingHeaderText = "Iam Mustapha";
const landingParagraphText = "Full Stack Developer";

async function textTypingEffect(element, text, time) {
  element.textContent = ""; /
  for (let i = 0; i < text.length; i++) {
    element.textContent += text[i];
    await new Promise((resolve) => setTimeout(resolve, time));
  }
}

async function startTyping() {
  await textTypingEffect(landingHeader, landingHeaderText, 35);
  await textTypingEffect(landingParagraph, landingParagraphText, 5);
}

startTyping();

قمت بتبسيط الأمر باستخدام حلقة for واحدة داخل textTypingEffect، وأصبح الكود أكثر وضوحًا من خلال فصل التأخير الزمني عن عملية إضافة الحروف.

وتم تحسين الأداء بشكل طفيف من خلال استخدام Promise واحدة فقط لكل نص بدلاً من إنشاء Promise جديدة لكل حرف.

رابط هذا التعليق
شارك على الشبكات الإجتماعية

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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.

  • إعلانات

  • تابعنا على



×
×
  • أضف...