Ajax هي أداة رئيسية في تطوير تطبيقات الويب الحديثة. يتيح لك إرسال واستقبال البيانات بشكل غير متزامن إلى الخادم ثم تحليلها في JavaScript. Ajax هو اختصار JavaScript غير المتزامن و XML (JavaScript غير المتزامن و XML).
ويرث اسم مواصفات AJAX الأساسية من كائن JavaScript المستخدم لإنشاء وبدء الطلبات: XMLHTTPrequest. هناك مستويان من هذه المواصفات. تنفذ جميع المتصفحات الرئيسية المستوى الأول ، والذي يمثل المستوى الأساسي للوظائف. يمتد المستوى الثاني من المواصفات الأولية ، ويتضمن أحداثًا إضافية وبعض الميزات لتسهيل التعاون مع عناصر النماذج ، ويدعم بعض المواصفات ذات الصلة.
1. يبدأ أياكس
يكمن مفتاح Ajax في كائن XMLHTTPrequest ، والطريقة لفهم هذا الكائن هي النظر إلى مثال. يعرض الرمز التالي الاستخدام البسيط لكائن XMLHTTPrequest:
<! doctype html> <html lang = "en"> <head> <meta charset = "utf-8" <title> مثال </title> </head> <body> <viv> <button> التفاح <//button> </button> cherries </button> </button> type = "application/javaScript"> var buttons = document.getElementSbyTagName ("button") ؛ لـ (var i = 0 ؛ i <buttons.length ؛ i ++) {buttons [i] .onclick = handlebuttonpress ؛ } // سيقوم البرنامج النصي بالاتصال بهذه الوظيفة للاستجابة لدالة حدث CLICK لعنصر CLICK BUNTY BEADBUTTONPRESS (e) {// إنشاء كائن XMLHTPREQUEST جديد var httprequest = new xmlhtprequest () ؛ // قم بتعيين معالج أحداث لحدث onReadyStateChange httprequest.onreadyStateChange = HandlerSponse ؛ // استخدم الطريقة المفتوحة لتحديد طريقة HTTP وعنوان URL لطلب (أي ، أخبر كائن httprequest ما تريد القيام به) httprequest.open ("get" ، etarget.innerhtml+". html") ؛ // لا يتم إرسال أي بيانات إلى الخادم هنا ، لذلك لا تحتوي طريقة الإرسال على معلمات متاحة httprequest.send () ؛ } // معالجة الاستجابة // بمجرد استدعاء البرنامج النصي طريقة إرسال ، سيرسل المتصفح طلبًا إلى الخادم في الخلفية. نظرًا لأن الطلب تتم معالجته في الخلفية ، يعتمد Ajax على الأحداث لإبلاغ تقدم الطلب. وظيفة معالج الوظائف (e) {// عندما يتم تشغيل حدث onReadyStateChange ، سيقوم المتصفح بتمرير كائن حدث إلى وظيفة المعالج المحددة ، وسيتم تعيين الخاصية المستهدفة على xmlhttprequest المرتبطة بهذا الحدث إذا ( document.getElementById ("Target"). innerhtml = e.target.Responsetext ؛ // إظهار محتوى المستند المطلوب}} </script> </body> </html>ثلاثة وثائق إضافية بسيطة للغاية:
<! doctype html> <html lang = "en"> <head> <meta charset = "utf-8"> <title> التفاح </title> <style> img {float: left ؛ padding: 2px ؛ margin: 5px ؛ الحدود: متوسطة مزدوجة اللون الخلفية: lightgrey ؛ العرض: 100px ؛ الارتفاع: 100px ؛} </style> </head> <body> <p> <img src = "../ img/show-page/img_apples.jpg"/> صفحة للتفاح. </p> </body> </html>يظهر التأثير في الشكل أدناه:
نظرًا لأن المستخدم ينقر على كل زر فاكهة ، فإن المتصفح ينفذ بشكل غير متزامن ويسترجع المستند المطلوب ، بينما لا يتم إعادة تحميل المستند الرئيسي. هذا هو سلوك أياكس النموذجي.
2. باستخدام أحداث Ajax
بعد إنشاء واستكشاف مثال بسيط ، يمكنك البدء في البحث في الميزات التي يدعمها كائن XMLHTTPrequest وكيفية استخدامها في طلبك. نقطة البداية هي الأحداث الإضافية المحددة في مواصفات المستوى الثاني:
يتم تشغيل معظم هذه الأحداث في وقت محدد أثناء الطلب. الحدثان هما استثناءات ، ReadyStateChange والتقدم ، والتي يمكن تشغيلها عدة مرات لتوفير تحديثات التقدم.
عندما يتم جدولة هذه الأحداث ، يستخدم المتصفح كائن حدث منتظم لحدث ReadyStateChange وكائن تقدم لأحداث أخرى. يحدد كائن ProgressEvent جميع أعضاء كائن الحدث ويضيف هؤلاء الأعضاء الموصوفين في الشكل التالي:
يوضح الرمز التالي كيفية استخدام هذه الأحداث:
<! doctype html> <html lang = "en"> <head> <meta charset = "utf-8"> <title> مثال </title> <style> table {margin: 10px ؛ collapse: collapse ؛ تعويم: left ؛} div {margin: 10px ؛} td ، th {padding: 4px ؛} </style> </head> <body> <viv> <button> التفاح </button> <button> cherries </button> bunanas </button> </div> type = "application/javaScript"> var buttons = document.getElementSbyTagName ("button") ؛ لـ (var i = 0 ؛ i <buttons.length ؛ i ++) {buttons [i] .onclick = handlebuttonpress ؛ } var httprequest ؛ وظيفة handlebuttonpress (e) {clearEventDetails () ؛ httprequest = new xmlhttprequest () ؛ httprequest.onreadyStateChange = معالجات ؛ httprequest.onerror = handleRor ؛ httprequest.onload = handleLoad ؛؛ httprequest.onloadend = handloadend ؛ httprequest.onloadStart = HandleLoadStart ؛؛ httprequest.onprogress = مقابض ؛ httprequest.open ("get" ، e.target.innerhtml+". html") ؛ httprequest.send () ؛ } دالة معالج (e) {displayEventDetails ("ReadyState ("+httprequest.readyState+")") if ( }} دالة handleRror (e) {displayeventDetails ("error" ، e) ؛} function handleLoad (e) {displayEventDetails ("load" ، e) ؛} function handleloadend (e) {displayeventdetails ("loadend" ، e) ؛ الوظيفة handleLoadStart (e) {displayEventDetails ("loadStart" ، e) ؛} وظيفة genterprogress (e) {displayEventDetails ("progress" ، e) ؛} وظيفة cleareventdetails () {document.getElementById ("الأحداث"). innerhtml = "<tr> <th> الحدث </th> <h> lengthComputable </h> <th> تم تحميله </th> <th> المجموع </th>" ؛ } دالة DisplayEventDetails (eventName ، e) {if (e) {document.getElementById ("الأحداث"). innerhtml+= "<tr> <td>"+eventName+"</td> <td> E.total+"</td> </tr>" ؛ } آخر {document.getElementById ("الأحداث"). innerhtml+= "<tr> <td>"+eventName+"</td> <td> na </td> <td> na </td> <td> na </td> <td> na </td> </tr>" ؛ }} </script> </body> </html>هذا هو تباين في المثال السابق ، حيث سجل معالجًا لبعض الأحداث وإنشاء سجل لكل حدث معالجته في عنصر جدول. من الصورة التالية ، يمكنك معرفة كيفية قيام متصفح Firefox بإعداد هذه الأحداث.
3. التعامل مع الأخطاء
يجب الانتباه إلى نوعين من الأخطاء عند استخدام AJAX. الفرق بينهما ينبع من وجهات نظر مختلفة.
النوع الأول من الخطأ هو مشكلة يتم رؤيتها من منظور كائن XMLHTTPrequest: بعض العوامل تمنع الطلب من إرسالها إلى الخادم. على سبيل المثال ، لا يمكن لـ DNS حل اسم المضيف ، أو يتم رفض طلب الاتصال ، أو أن عنوان URL غير صالح.
النوع الثاني من المشكلة هو المشكلة التي شوهدت من منظور التطبيق ، وليس كائن XMLHTTPrequest. تحدث عند إرسال الطلب بنجاح إلى الخادم ، والذي يتلقى الطلب ، ويعالج ويولد استجابة ، لكن الاستجابة لا تشير إلى ما تتوقعه. على سبيل المثال ، إذا لم يكن عنوان URL المطلوب موجودًا ، فسيحدث هذا النوع من المشكلة.
هناك ثلاث طرق للتعامل مع هذه الأخطاء ، كما هو موضح في الكود التالي:
3.1 التعامل مع أخطاء الإعداد
النوع الأول من المشكلة التي يجب التعامل معها هو تمرير بيانات غير صحيحة إلى كائن XMLHTTPRESQUEST ، مثل عنوان URL غير الصحيح. فهي عرضة للغاية للحدوث عند إنشاء عناوين URL بناءً على إدخال المستخدم. لمحاكاة هذا النوع من المشكلات ، يحتوي المستند أعلاه على زر يضيف عنوان URL سيئًا (عنوان URL الخاطئ). سيؤدي الضغط على هذا الزر إلى استدعاء الطريقة المفتوحة في النموذج التالي:
httprequest.open ("get" ، "http: //")
هذا خطأ يمنع تنفيذ الطلب ، ويتم إلقاء خطأ عندما يحدث مثل هذا الحدث في كائن XMLHTTPrequest. هذا يعني أن هناك حاجة إلى عبارة CATPLE لتطويق الكود الذي يحدد الطلب ، مثل هذا:
حاول {... httprequest.open ("get" ، "http: //") ... httprequest.send () ؛ } catch (خطأ) {displayerrormsg ("Try/Catch" ، error.message)}يمنحك شرط الصيد فرصة للتعافي من الخطأ. يمكنك اختيار المطالبة بالمستخدم للحصول على قيمة ، أو العودة إلى عنوان URL الافتراضي ، أو ببساطة تجاهل الطلب. في هذا المثال ، يتم استدعاء وظيفة DisplayerRormsg لعرض رسالة الخطأ.
3.2 معالجة أخطاء طلب
يحدث النوع الثاني من الخطأ عند إنشاء الطلب ولكن هناك أخطاء أخرى. لمحاكاة هذا النوع من المشكلات ، تمت إضافة زر مضيف سيء (مضيف خطأ) في المثال. عند الضغط على هذا الزر ، سيتم استدعاء الطريقة المفتوحة للوصول إلى عنوان URL غير متوفر:
httprequest.open ("get" ، http: //www.ycdoitt.com/nopage.html)هناك مشكلتان مع عنوان URL هذا. المشكلة الأولى هي أنه لا يمكن حل اسم المضيف بواسطة DNS ، لذلك لا يمكن للمتصفح إنشاء اتصال خادم. تعرف هذه المشكلة أن كائن XMLHTTPrequest يصبح واضحًا فقط عندما يبدأ في إنشاء الطلب ، لذلك يشير إلى أخطاء بطريقتين. إذا قمت بتسجيل مستمع لحدث خطأ ، فسيقوم المتصفح بإرسال كائن حدث إلى المستمع الخاص بك. فيما يلي الوظائف المستخدمة في المثال:
دالة HandleRror (e) {displayerrorrormsg ("Error Event" ، httprequest.status + httprequest.statustext) ؛ }عند حدوث مثل هذه الأخطاء ، تعتمد درجة المعلومات التي يمكن الحصول عليها من كائن XMLHTTPrequest على المتصفح. لسوء الحظ ، في معظم الحالات ، سيتم الحصول على الحالة التي تبلغ قيمة 0 وقيمة فارغة.
المشكلة الثانية هي أن عنوان URL والطلب الذي تم إنشاؤه لهما مصادر مختلفة ، والتي لا يسمح بها افتراضيًا. يمكنك عادة إرسال طلبات Ajax فقط إلى عنوان URL للأصل نفسه الذي يقوم بتحميل البرنامج النصي. عندما يبلغ المتصفح عن هذه المشكلة ، قد يتم طرح خطأ أو قد يتم تشغيل حدث خطأ. متصفحات مختلفة تتعامل معها بشكل مختلف. تحقق المتصفحات المختلفة أيضًا من المصدر في نقاط مختلفة في الوقت المناسب ، مما يعني أن المتصفح قد لا يُرى دائمًا وهو يسلط الضوء على نفس المشكلة. يمكن استخدام مشاركة الموارد عبر الأصل لتجاوز القيود المتماثلة.
3.3 معالجة أخطاء التطبيق
يحدث النوع الأخير من الخطأ عند اكتمال الطلب بنجاح (من منظور كائن XMLHTTPrequest) ، لكنه لا يعيد البيانات التي تريدها. لإنشاء مثل هذه المشكلات ، أضف زرًا مع خيار التسمية في المثال أعلاه. سيؤدي الضغط على هذا الزر إلى إنشاء عنوان URL للطلب على غرار أزرار التفاح والكرز والموز ، لكن مستند Cucumber.html غير موجود على الخادم.
لا يوجد خطأ في هذه العملية نفسها (لأنه تم الانتهاء من الطلب) ، ومن الضروري تحديد ما يحدث بناءً على سمة الحالة. عند طلب مستند موجود ، سيتم الحصول على رمز الحالة 404 ، مما يعني أنه لا يمكن للخادم العثور على المستند المطلوب. يمكنك أن ترى كيف يعالج المثال رموز الحالة بخلاف 200 (بمعنى موافق):
if (httprequest.status == 200) {target.innerhtml = httprequest.responsetext ؛ } آخر {document.getElementById ("statusMsg"). innerhtml = "الحالة:" + httprequest.status + "" + httprequest.statustext ؛ }في هذا المثال ، يتم عرض قيم الحالة والثانية ببساطة. في التطبيقات الحقيقية ، يجب تنفيذ الاسترداد بطريقة مفيدة وذات مغزى (مثل عرض محتوى بديل أو مستخدمين تحذيرين من وجود مشكلة ، اعتمادًا على أي واحد أكثر ملاءمة للتطبيق).
4. احصل وضبط الرؤوس
باستخدام كائن XMLHTTPRequest ، يمكنك تعيين رأس الطلب المرسلة إلى الخادم والرأس في استجابة الخادم.
4.1 الكتابة فوق طريقة HTTP للطلبات
عادةً ليس من الضروري إضافة أو تعديل الرأس في طلب AJAX. يعرف المتصفح ما الذي يجب إرساله ، ويعرف الخادم كيفية الرد. ومع ذلك ، هناك عدة استثناءات. الأول هو رأس X-HTTP-Method-Override.
غالبًا ما يتم استخدام معيار HTTP لطلب ونقل مستندات HTML على الإنترنت ، ويحدد العديد من الطرق. معظم الناس يعرفون عن GET والنشر لأنهم الأكثر استخدامًا على نطاق واسع. ومع ذلك ، هناك طرق أخرى (بما في ذلك وضع وحذف) يتم استخدامها لإعطاء معنى لعنوان URL المطلوب للخادم ، وهذا الاستخدام في ارتفاع. على سبيل المثال ، إذا كنت ترغب في عرض سجل مستخدم ، فيمكنك إنشاء مثل هذا الطلب:
httprequest.open ("get" ، "http: // myserver/records/freeman/adam") ؛يتم عرض طريقة HTTP فقط وعنوان URL المطلوب هنا. لكي يعمل هذا الطلب بسلاسة ، يجب أن يكون جانب الخادم قادرًا على فهم الطلب بواسطة التطبيق وتحويله إلى جزء مناسب من البيانات ليتم إرساله إلى الخادم. إذا كنت ترغب في حذف البيانات ، فيمكنك كتابتها مثل هذا:
httprequest.open (" delete " ، "http: // myserver/records/freeman/adam") ؛المفتاح هنا هو التعبير عن ما تريد أن يفعله الخادم عبر HTTP ، بدلاً من تشفيره في عنوان URL بطريقة ما.
تكمن مشكلة استخدام أساليب HTTP بهذه الطريقة في أن العديد من تقنيات الويب السائدة تدعم فقط GET and POST ، والعديد من جدران الحماية تسمح فقط بتمرير طلبات الحصول على. هناك نهج اصطناعي لتجنب هذا القيد ، وهو استخدام رأس X-HTTP-Method-Override لتحديد طريقة HTTP التي تريد استخدامها ، ولكن يتم تسويق النموذج وإرسال طلب نشر. عرض الكود كما يلي:
<! doctype html> <html lang = "en"> <head> <meta charset = "utf-8" <title> مثال </title> </head> <body> <viv> <button> التفاح <//button> </button> cherries </button> </button> document.getElementsByTagName ("Button") ؛ لـ (var i = 0 ؛ i <buttons.length ؛ i ++) {buttons [i] .onclick = handlebuttonpress ؛ } var httprequest ؛ دالة HandleButtonPress (e) {httprequest = new xmlhttprequest () ؛ httprequest.onreadyStateChange = معالجات ؛ httprequest.open ("get" ، e.target.innerhtml+". html") ؛ httprequest.setRequestHeader ("x-http-method-override" ، "delete") ؛ httprequest.send () ؛ } دالة HandleRror (e) {displayerrormsg ("حدث الخطأ" ، httprequest.status+httprequest.statustext) ؛ } وظيفة معالج () {if (httprequest.readyState == 4 && httprequest.status == 200) {document.getElementById ("Target"). innerhtml = httprequest.responsetext ؛ }} </script> </body> </html>في هذا المثال ، يتم استخدام طريقة setRequestHeader على كائن XMLHTTPrequest للإشارة إلى أن الطلب مطلوبة في شكل طريقة حذف HTTP. يرجى ملاحظة أنني قمت بتعيين هذا الرأس فقط بعد الاتصال بالطريقة المفتوحة. إذا حاولت استخدام طريقة setRequestHeader قبل الطريقة المفتوحة ، فإن كائن XMLHTTPrequest يلقي خطأ.
PS: يتطلب الكتابة فوق HTTP إطار تطبيق الويب من جانب الخادم لفهم اتفاقية Override X-HTTP ، ويجب تعيين تطبيق من جانب الخادم للعثور على طرق HTTP الأقل وفهمها.
4.2 تعطيل التخزين المؤقت للمحتوى
الرأس الثاني المفيد الذي يمكن إضافته إلى طلبات AJAX هو التحكم في ذاكرة التخزين المؤقت ، وهو أمر مفيد بشكل خاص عند كتابة البرامج النصية وتصحيح الأخطاء. تم الحصول على محتوى ذاكرة التخزين المؤقت لبعض المتصفحات من خلال طلبات Ajax ولن يطلبها مرة أخرى أثناء جلسة التصفح. بالنسبة للمثال السابق ، فهذا يعني أن التغييرات على Apples.html و cherries.html و bananas.html لن تنعكس على الفور في المتصفح. يوضح الرمز التالي كيفية تعيين الرؤوس لتجنب ذلك:
httprequest = new xmlhttprequest () ؛ httprequest.onreadyStateChange = معالجات ؛ httprequest.open ("get" ، e.target.innerhtml+". html") ؛ httprequest.setRequestHeader ("Cache-Control" ، "no-cache") ؛ httprequest.send () ؛طريقة ضبط الرأس هي نفسها كما في المثال السابق ، ولكن هذه المرة يكون الرأس هو التحكم في ذاكرة التخزين المؤقت ، والقيمة المطلوبة هي عدم ذاكرة التخزين المؤقت. بعد وضع هذا البيان ، إذا كان المحتوى المطلوب من خلال تغيير AJAX ، فسيتم عكس ذلك في المرة التالية التي يتم فيها طلب المستند.
4.3 اقرأ رأس الاستجابة
يمكن قراءة رأس HTTP الذي أرسله الخادم عند الاستجابة لطلب AJAX من خلال أساليب GetResponseHeader و GetAllResponseHeaders. في معظم الحالات ، لا تحتاج إلى الاهتمام بما هو موجود في الرأس ، لأنها جزء من المعاملات التفاعلية بين المتصفح والخادم. يوضح الرمز التالي كيفية استخدام هذه الخاصية:
<! doctype html> <html lang = "en"> <head> <meta charset = "utf-8"> <meta content = "width = width device ، order-scalable = no" name = "iewport" /> <meta name = "content" content = ye chaoluka " /> href = "../ img/ycdoit.ico" type = "image/x-icon" rel = "stortcut icon"/> <style> #alleaders ، #cheader {border: medium solid black ؛ padding </cherries ؛ margin: 2px ؛} <NUNTY> BANANAS </button> </viv> <div id = "keader"> </viv> <div id = "allheaders"> </viv> <div id = "target"> اضغط على زر </div> <script> var buttons = document.getElementSbyTagname ("button") ؛ لـ (var i = 0 ؛ i <buttons.length ؛ i ++) {buttons [i] .onclick = handlebuttonpress ؛ } var httprequest ؛ دالة HandleButtonPress (e) {httprequest = new xmlhttprequest () ؛ httprequest.onreadyStateChange = معالجات ؛ httprequest.open ("get" ، e.target.innerhtml+". html") ؛ httprequest.setRequestHeader ("Cache-Control" ، "no-cache") ؛ httprequest.send () ؛ } دالة معالجات () {if (httprequest.readyState == 2) {document.getElementById ("allheaders"). innerhtml = httprequest.getAllResponseHeaders () ؛ document.getElementById ("cheader"). innerhtml = httprequest.getResponseHeader ("type-type") ؛ } آخر إذا (httprequest.readyState == 4 && httprequest.status == 200) {document.getElementById ("target"). innerhtml = httprequest.responsetext ؛ }} </script> </body> </html>العروض كما يلي:
وفقًا لهذا الرقم ، يمكننا أن نرى أن برنامج خادم الويب الذي يعمل عليه خادم التطوير هو IDEAMEG IDEA 15.0.4 ، وفي المرة الأخيرة التي تم فيها تعديل وثيقة التفاح.