jQuery والتعامل مع DOM

AJAX مع jQuery - الجزء الأول

15 دقيقة الدرس 26 من 30

مقدمة إلى AJAX مع jQuery

تتيح AJAX (JavaScript وXML غير المتزامنة) تحديث أجزاء من صفحة الويب دون إعادة تحميل الصفحة بأكملها. توفر jQuery طرقاً قوية وبسيطة للعمل مع AJAX، مما يجعل التواصل مع الخادم سلساً وفعالاً.

ما هي AJAX؟

تمكن AJAX من:

  • الاتصال غير المتزامن: إرسال واستقبال البيانات من الخوادم دون تحديث الصفحة
  • تجربة مستخدم أفضل: عدم وميض الصفحة أو الانتظار لإعادة التحميل الكاملة
  • تفاعلات أسرع: تحميل البيانات التي تحتاجها فقط
  • محتوى ديناميكي: تحديث أجزاء محددة من صفحتك
ملاحظة: على الرغم من أن AJAX في الأصل تعني "JavaScript وXML غير المتزامنة"، إلا أن التطبيقات الحديثة تستخدم عادةً JSON بدلاً من XML لتبادل البيانات.

الدالة $.ajax()

الدالة $.ajax() هي أقوى دالة AJAX في jQuery. توفر تحكماً كاملاً في طلبات HTTP:

البنية الأساسية:
$.ajax({
    url: 'https://api.example.com/data',
    method: 'GET',
    success: function(response) {
        console.log('نجح:', response);
    },
    error: function(xhr, status, error) {
        console.log('خطأ:', error);
    }
});

خيارات $.ajax() الشائعة

مثال على الإعدادات الكاملة:
$.ajax({
    // إعدادات الطلب
    url: '/api/users',
    method: 'GET',              // طريقة HTTP (GET, POST, PUT, DELETE)
    data: { page: 1, limit: 10 }, // البيانات المراد إرسالها
    dataType: 'json',           // نوع الاستجابة المتوقعة
    timeout: 5000,              // مهلة الطلب (ميلي ثانية)

    // الرؤوس
    headers: {
        'Authorization': 'Bearer token123',
        'X-Custom-Header': 'value'
    },

    // دوال الاستدعاء
    success: function(data, textStatus, xhr) {
        console.log('تم استلام البيانات:', data);
    },

    error: function(xhr, textStatus, errorThrown) {
        console.log('فشل الطلب:', textStatus);
    },

    complete: function(xhr, textStatus) {
        console.log('اكتمل الطلب');
    },

    // الأحداث
    beforeSend: function(xhr) {
        console.log('جاري إرسال الطلب...');
        $('#loader').show();
    }
});

طلبات GET باستخدام $.ajax()

مثال: تحميل بيانات المستخدم
<div id="user-profile">
    <button id="load-user">تحميل الملف الشخصي</button>
    <div id="profile-content"></div>
</div>

<script>
$('#load-user').click(function() {
    $.ajax({
        url: 'https://jsonplaceholder.typicode.com/users/1',
        method: 'GET',
        dataType: 'json',
        beforeSend: function() {
            $('#profile-content').html('<p>جاري التحميل...</p>');
        },
        success: function(user) {
            var html = '<h3>' + user.name + '</h3>' +
                      '<p>البريد الإلكتروني: ' + user.email + '</p>' +
                      '<p>الهاتف: ' + user.phone + '</p>' +
                      '<p>الموقع: ' + user.website + '</p>';
            $('#profile-content').html(html);
        },
        error: function(xhr, status, error) {
            $('#profile-content').html('<p style="color: red;">فشل تحميل الملف الشخصي</p>');
        }
    });
});
</script>

طلبات POST باستخدام $.ajax()

مثال: إنشاء منشور جديد
<form id="new-post-form">
    <input type="text" id="post-title" placeholder="العنوان">
    <textarea id="post-body" placeholder="المحتوى"></textarea>
    <button type="submit">إنشاء منشور</button>
</form>
<div id="post-result"></div>

<script>
$('#new-post-form').submit(function(e) {
    e.preventDefault();

    var postData = {
        title: $('#post-title').val(),
        body: $('#post-body').val(),
        userId: 1
    };

    $.ajax({
        url: 'https://jsonplaceholder.typicode.com/posts',
        method: 'POST',
        data: JSON.stringify(postData),
        contentType: 'application/json',
        dataType: 'json',
        success: function(response) {
            $('#post-result').html(
                '<div style="color: green;">' +
                'تم إنشاء المنشور برقم: ' + response.id +
                '</div>'
            );
            $('#new-post-form')[0].reset();
        },
        error: function() {
            $('#post-result').html(
                '<div style="color: red;">فشل إنشاء المنشور</div>'
            );
        }
    });
});
</script>

معالجة بيانات الاستجابة

مثال: معالجة أنواع الاستجابة المختلفة
// استجابة JSON
$.ajax({
    url: '/api/products.json',
    dataType: 'json',
    success: function(products) {
        products.forEach(function(product) {
            console.log(product.name, product.price);
        });
    }
});

// استجابة HTML
$.ajax({
    url: '/templates/product-card.html',
    dataType: 'html',
    success: function(html) {
        $('#products-container').append(html);
    }
});

// استجابة نصية
$.ajax({
    url: '/data/readme.txt',
    dataType: 'text',
    success: function(text) {
        $('#content').text(text);
    }
});

// استجابة XML
$.ajax({
    url: '/data/products.xml',
    dataType: 'xml',
    success: function(xml) {
        $(xml).find('product').each(function() {
            var name = $(this).find('name').text();
            console.log(name);
        });
    }
});

معاملات الطلب

مثال: إرسال معاملات الاستعلام
// تدوين الكائن (موصى به)
$.ajax({
    url: '/api/search',
    data: {
        q: 'laptop',
        category: 'electronics',
        minPrice: 500,
        maxPrice: 2000
    },
    success: function(results) {
        console.log(results);
    }
});
// يرسل: /api/search?q=laptop&category=electronics&minPrice=500&maxPrice=2000

// تدوين النص
$.ajax({
    url: '/api/search',
    data: 'q=laptop&category=electronics',
    success: function(results) {
        console.log(results);
    }
});
نصيحة: استخدم دائماً تدوين الكائن لمعاملات البيانات. ستقوم jQuery تلقائياً بترميز القيم في URL ومعالجة الأحرف الخاصة بشكل صحيح.

تعيين رؤوس الطلب

مثال: رؤوس مخصصة لمصادقة API
$.ajax({
    url: '/api/protected-data',
    method: 'GET',
    headers: {
        'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
        'X-API-Key': 'your-api-key-here',
        'X-Requested-With': 'XMLHttpRequest'
    },
    success: function(data) {
        console.log('البيانات المحمية:', data);
    },
    error: function(xhr) {
        if (xhr.status === 401) {
            console.log('غير مصرح - رمز غير صالح');
        }
    }
});

المهلة وإعادة المحاولة

مثال: معالجة المهل الزمنية
function loadDataWithTimeout() {
    $.ajax({
        url: '/api/slow-endpoint',
        timeout: 3000, // 3 ثوانٍ
        success: function(data) {
            $('#result').html('تم تحميل البيانات بنجاح');
        },
        error: function(xhr, status, error) {
            if (status === 'timeout') {
                $('#result').html('انتهت مهلة الطلب. يرجى المحاولة مرة أخرى.');
            } else {
                $('#result').html('خطأ: ' + error);
            }
        }
    });
}

// آلية إعادة المحاولة
function loadDataWithRetry(maxRetries) {
    var attempts = 0;

    function attempt() {
        $.ajax({
            url: '/api/unreliable-endpoint',
            success: function(data) {
                console.log('نجح بعد', attempts + 1, 'محاولات');
            },
            error: function() {
                attempts++;
                if (attempts < maxRetries) {
                    console.log('محاولة إعادة', attempts);
                    setTimeout(attempt, 1000); // إعادة المحاولة بعد ثانية واحدة
                } else {
                    console.log('فشل بعد', maxRetries, 'محاولات');
                }
            }
        });
    }

    attempt();
}

loadDataWithRetry(3);
تحذير: كن حذراً مع آليات إعادة المحاولة التلقائية. الكثير من المحاولات السريعة يمكن أن يثقل كاهل الخوادم أو يؤدي إلى تفعيل حد المعدل. قم دائماً بتطبيق التأخير الأسي أو التأخيرات بين المحاولات.

دالة الاستدعاء complete()

مثال: التنظيف بعد الطلب
$('#submit-button').click(function() {
    var $button = $(this);

    $.ajax({
        url: '/api/save-data',
        method: 'POST',
        data: { value: 'test' },
        beforeSend: function() {
            $button.prop('disabled', true).text('جاري الحفظ...');
            $('#loader').show();
        },
        success: function(response) {
            $('#message').html('<span style="color: green;">تم الحفظ!</span>');
        },
        error: function() {
            $('#message').html('<span style="color: red;">خطأ!</span>');
        },
        complete: function() {
            // يتم التشغيل دائماً، سواء نجح أو فشل
            $button.prop('disabled', false).text('حفظ');
            $('#loader').hide();

            // مسح الرسالة بعد 3 ثوانٍ
            setTimeout(function() {
                $('#message').empty();
            }, 3000);
        }
    });
});
تمرين عملي:

أنشئ ميزة البحث عن المستخدمين:

  1. أضف حقل إدخال للبحث وزر
  2. استخدم $.ajax() لجلب البيانات من: https://jsonplaceholder.typicode.com/users
  3. تصفية المستخدمين حسب الاسم بناءً على إدخال البحث
  4. عرض بطاقات المستخدمين مع الاسم والبريد الإلكتروني والشركة
  5. إظهار مؤشر تحميل أثناء الجلب
  6. معالجة الأخطاء بشكل صحيح مع رسائل مناسبة
  7. إضافة رسالة "لا توجد نتائج" عندما يعيد البحث فارغاً

إضافي: أضف دالة debounce لمنع الطلبات عند كل ضغطة مفتاح.

أفضل الممارسات

  • عالج الأخطاء دائماً: قدم رسائل خطأ مفيدة للمستخدمين
  • استخدم مؤشرات التحميل: أظهر ملاحظات مرئية أثناء الطلبات
  • عيّن مهل مناسبة: منع الانتظار إلى ما لا نهاية
  • عطّل واجهة المستخدم أثناء الطلبات: منع الإرسال المكرر
  • تحقق من البيانات قبل الإرسال: قلل من طلبات الخادم غير الضرورية
  • استخدم HTTPS: ضمان نقل البيانات الآمن
  • عالج جميع رموز الحالة: 401 (غير مصرح)، 404 (غير موجود)، 500 (خطأ في الخادم)

الخلاصة

في هذا الدرس، تعلمت:

  • ما هي AJAX ولماذا هي مهمة
  • كيفية استخدام $.ajax() مع الإعدادات الكاملة
  • إجراء طلبات GET و POST
  • معالجة أنواع الاستجابة المختلفة (JSON، HTML، نص، XML)
  • تعيين رؤوس ومعاملات الطلب المخصصة
  • تطبيق آليات المهلة وإعادة المحاولة
  • استخدام دوال الاستدعاء beforeSend وsuccess وerror وcomplete

في الدرس التالي، سنستكشف طرق AJAX المختصرة في jQuery والتقنيات المتقدمة مثل التخزين المؤقت والوعود ومعالجة الطلبات المتعددة.