home الرئيسيةpeople_outline الأعضاء vpn_key دخول
chatالمواضيع الأخيرة
زراعة الشعر في تركياaccess_time2019-04-16, 9:25 pmpersonتسويق ستة
new_releasesأفضل 10 أعضاء في هذا الأسبوع
new_releasesأفضل 10 أعضاء في هذا الشهر
bubble_chartالمتواجدون الآن ؟
ككل هناك 5 عُضو متصل حالياً :: 0 عضو مُسجل, 0 عُضو مُختفي و 5 زائر

لا أحد

مُعاينة اللائحة بأكملها

أكبر عدد للأعضاء المتواجدين في هذا المنتدى في نفس الوقت كان 494 بتاريخ 2019-03-19, 11:43 am

طريقة عرض الأقسام

لونك المفضل

ماهي الوعود في الجافاسكربت


[ندعوك للتسجيل في المنتدى أو التعريف بنفسك لمعاينة هذا الرابط]
 
السلام عليكم و رحمة الله و بركاته
جميع الامثلة ستكون ذات علاقة بالـ Node.JS و هذا الدرس سيكون مقدمة لدرس آخر

 
في السابق تحدثت عن مفهوم الـcallback ، إيجابياته، سلبياته و تطرقت لـ السلبية الأكبر وهي جحيم الكولباك callback hell وهو عبارة عن عدد من الدوال المتداخلة في بعضها ، تشكل هرم من الأقواس وتعتمد كل منها على مخرجات الاخرى حيث يصعب بعد ذلك تطوير هذه الجزئية من الكود لكثرة التداخلات وكذلك تصعب عملية حصر الاخطاء، وهو بالفعل ما يسمى بـ جحيم الكولباك (كما اسلفنا) و في الصورة ادناه مثال على ذلك.
[ندعوك للتسجيل في المنتدى أو التعريف بنفسك لمعاينة هذه الصورة]
 
لهذا .. وٌجِد بما يٌسمى بالـ وعود "Promises" حيث يعمل الوعد على تمثيل الناتج لأي عملية / دالة asynchronous تريدها بطريقة اكثر (حضارية) ان صح التعبير، و يكون الوعد في ثلاث حالات three states:

  • pending : الحالة الاولية للوعد، في حالة التأهب لاستقبال الوعد.
  • resolved أو fulfilled : تم إيفاء الوعد وانتهى عند هذا الحد.
  • rejected : تم رفض الوعد مع السبب وانتهى عند هذا الحد.

 

التطبيق النظري للوعود

للوعود عدة أشكال/ميثودز syntax واهمها هي:

الكود:

function GetData() {
    return new Promise(function (resolve, reject) {
        if(/* condition true and satisfied */)
            resolve (/* results */)
        else
            reject (/* reason/s why it has been rejected */)   
    });
}



 
كما نلاحظ في المثال أعلاه، اولا قمنا بإنشاء وعد new Promise و من ثم الدالة التي تأخذ متيغيرين إثنين resolve في حالة ايفاء الوعد و reject في حالة الرفض ( وقد تكون في حالة وجود مشكلة error ).
 

التطبيق العملي للوعود

في جميع التطبيقات على ارض الواقع, يقع المبرمج في امور معقدة قد تتطلب منه استخدام هذا النوع من الدوال, ومثالا على ذلك - الحالة 1:

  • قاعدة بيانات لمدرسة تحتوي على عدة جداول منها 3 جداول رئيسية ( التي نحتاجها فقط).
  • جدول يحتوي على معلومات الطلبة (ID, FullName, AcademicNumber, DOB).
  • جدول آخر يحتوي على المواد التي يدرسها الطالب (ID, CourseID, StudentID).
  • جدول ثالث يحتوي على (ID, CourseCode, CourseLevel, CourseHours)

مع الأخذ بالاعتبار ان الـ ID في كل جدول عيارة عن Primary Key Auto Inc, ماذا لو ادرت ان تعرف *اسماء المواد التي يدرسها الطالب و بالأسماء اعني CourseCode* ؟ حتما ستقع في جحيم الكولباك , لانك اولا تختار ID الطالب وتتاكد من وجوده ام عدمه, ان وجد انتقلت للمرحلة الثانية وهي اختيار الـ CourseID مع وجود StudentID و التأكد من وجودة ام عدمة و اخيرا اخيار الـ CourseCode من الجدول الاخير و التاكد من وجوده ام عدمة.
المشكلة في المثال ليست "وجود ام عدم" النتيجة, بل في الدوال التي ستكون مترابطة في بعضها بما لا يقل عن 3 بالتالي ستصعب عملية حصار الأخطاء او التعامل ككل مع المسألة , وان تعقدت اكثر ( الله يستر).
 
وهنا يأتي دور الـ Promises في تفكيك هذه العملية الى اجزاء, دوال بسيطة, ونبدأ بكتابة دوال الـ Promises
 
[ندعوك للتسجيل في المنتدى أو التعريف بنفسك لمعاينة هذه الصورة]
 

الكود:

function CourseCodesByStudentID(...value) {
    return new Promise(function (resolve, reject) {
        var sql_query = 'SELECT `ID` As std_id FROM `students` WHERE `ID` = ?';
        var sql_parameters = [value[0]];
        db.connection.query(sql_query, sql_parameters, function (err, results, fields) {
            if (err) {
                reject(err);
            } else {
                if (results.length) {
                    resolve(results);
                } else {
                    reject('the student cannot be found');
                }
            }
        });
    });
}

function StudentCourses(...value) {
    return new Promise(function (resolve, reject) {
        var sql_query = 'SELECT `CourseID` FROM `StdCourses` WHERE `StudentID` = ?';
        var sql_parameters = [value[0]];
        db.connection.query(sql_query, sql_parameters, function (err, results, fields) {
            if (err) {
                reject(err);
            } else {
                if (results.length) {
                    // You can use Array.prototype.map() Or Array.prototype.forEach()
                    let coursesArray = [];
                    for (let i = 0; i < results.length; i++) {
                        coursesArray.push(results[i].CourseID);
                    }
                    resolve(coursesArray);
                } else {
                    reject('no courses found for this student');
                }
            }
        });
    });
}

function CoursesCodes(...value) {
    return new Promise(function (resolve, reject) {
        var sql_query = 'SELECT `CourseCode` FROM `Courses` WHERE `ID` IN (?)';
        var sql_parameters = [value[0]];
        db.connection.query(sql_query, sql_parameters, function (err, results, fields) {
            if (err) {
                reject(err);
            } else {
                if (results.length) {
                    resolve(results);
                } else {
                    reject('no courses found');
                }
            }
        });
    });
}


 
وكما هو موضح مخرجات كل دالة في الأسفل, في هذه المرحلة جميل الوعود في حالة pending في انتظار التفعيل او البدأ في عملية الرفض ام القبول وتكون كالتالي:

  •  للحصول على مخرجات وعد واحد

[ندعوك للتسجيل في المنتدى أو التعريف بنفسك لمعاينة هذه الصورة]

الكود:

/* To get a resutls from one promise */
// let's assume that the StudentID is 20098821
CourseCodesByStudentID(20098821).then(function(results1){
    /*
        OUTPUT

        [
            {
                "std_id": 1234
            }

        ]

    */   
    let res_from_promise_1 = results1[0].std_id;
    console.log(res_from_promise_1);
   
})
.catch(function(err){
    console.log(err);
});


 

  • للحصول على مخرجات سلسلة من الوعود

[ندعوك للتسجيل في المنتدى أو التعريف بنفسك لمعاينة هذه الصورة]

الكود:

/* Chain of promises
Don't forget, we already assumed that the StudentID is 20098821, so this is how we pass it
*/
CourseCodesByStudentID(20098821).then(function(results1){
    /*
        OUTPUT

        [
            {
                "std_id": 1234
            }

        ]

    */
    let res_from_promise_1 = results1[0].std_id;


    // now we pass it to the second promise in this way
    return StudentCourses(res_from_promise_1); // fire the second Promise
})
.then(function(resutls2){
    /* 
        OUTPUT
        res_from_promise_2 == results2
            [
                105,
                325,
                987,
                536
            ]
    */
    let res_from_promise_2 = resutls2 // not necessary to declare a variable here, but I'm doing it just as an example that u might use it as u wish
    return CoursesCodes(res_from_promise_2); // fire the third Promise
})
.then(function (finalResutls) {
    console.log(finalResutls);
    /* 
        OUTPUT
        finalResutls
            [
                "CourseCode":"ENB101",
                "CourseCode": "FLK106",
                "CourseCode": "KLO204",
                "CourseCode": "ARB101",
            ]
    */
})
.catch(function(err){
    console.log(err);
});


 
و في الحالة الثانية للأستفادة اكثر من الـ Promises , * ماذا لو كان لديك تطبيق اخباري تزودة بالمعلومات بشكل متفرق, اي لا يعتمد على سيرفر خاص بك و لايعتمد على سيرفر واحد بل عدة * , ستحتاج في هذه الحالة الى Method تدعى race وهي اسم على مسمى حيث سيتم ايقاف الوعد عند اول resolve
 

الكود:

var Source1 = new Promise(function (resolve, reject) {
    var data_to_stringfy = {
        apiKey: "XKJS09sJFsg",
        path: "local"
    }
    var url = 'https://bahrain.news.com/api';
    var data = JSON.stringify(data_to_stringfy);
    request.post({
        headers: {
            'Content-Type': 'application/json'
        },
        url: url,
        body: data
    }, function (error, response, body) {
        if (error) reject(error);
        else {
            let parsedBody = JSON.parse(body);
            resolve(parsedBody);
        }
    });
});


var Source2 = new Promise(function (resolve, reject) {
    var url = "http://mysite.com/json";
    request.get({
        url: url
    }, function (error, response, body) {
        if (error) reject(error);
        else {
            resolve(body);
        }
    });
});


Promise.race([Source1, Source2])
.then(function(finalResult) {
// Both promises might be resolved but the results will be the first promise to finish, could be Source1 or Source2 it doesn't matter
console.log(finalResult);
})
.catch(function(error){
  console.log(error);
});


 
الحالة الثالثة والاخير التي سنعرضها في هذا الدرس هي * اي امر يتطلب عدة خطوات معينة لإستيفائة كـ عملية اطلاق الصاروخ حيث يجب ان تتم العملية بخطوات محددة و يجب ان تكون جميعها صحيحة " توفي الوعد" * ( بالعربي اما كلشي يمشي سليم ولا .. تجيب العيد ) , ستحتاج في هذه الحالة الى Method تدعى All يتم ايقاف الوعد فيها عند اول Reject على عكس Race

الكود:

var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
});
// expected output: Array [3, 42, "foo"]


 
{ الحمد لله أقصى مبلغ الحمد .. والشكر لله من قبل ومن بعد }
 
انتهى .. للأسئلة في التعليقات

تعاليق

لا يوجد حالياً أي تعليق
ارسال رد

هــــــام

ندعوك للتسجيل في المنتدى لتتمكن من ترك رد أو تسجيل الدخول اذا كنت من اسرة المنتدى

صلاحيات هذا المنتدى:
لاتستطيع الرد على المواضيع في هذا المنتدى