English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

تفسير XMLHttpRequest (ثانياً) خصائص الرد، البيانات الثنائية، مراقبة تقدم التحميل والتنزيل

تحليل وتشغيل خاصية responseXML 

إذا كنت تستخدم XMLHttpRequest للحصول على محتوى وثيقة XML عن بُعد، فإن خاصية responseXML ستكون DOM عنصرًا تم تحليله من وثيقة XML، مما يجعله صعبًا التشغيل والتحليل. هناك خمس طرق رئيسية لتحليل وثائق XML:
 1. استخدم XPath للوصول إلى جزء معين من الوثيقة.
 2. استخدم JXON لتحويله إلى شجرة جافا سكريبت.
 3. تحليل وتسلسل XML يدويًا إلى نص أو عنصر.
 4. استخدم XMLSerializer لتحويل شجرة DOM إلى نص أو ملف.
 5. إذا كنت تعرف مسبقًا محتوى وثيقة XML، يمكنك استخدام RegExp. إذا كانتRegExp تؤثر على الرمز الناتج عن الفواصل، قد ترغب في حذف جميع الفواصل. ومع ذلك، فإن هذا الأسلوب هو "وسيلة الأخيرة"، لأن إذا تغيرت كود XML بقليل، قد تفشل هذه الطريقة. 

تحليل وتشغيل خاصية responseText التي تحتوي على وثيقة HTML 

ملاحظة: يُسمح في معيار W3C XMLHttpRequest بتحليل HTML عبر خاصية XMLHttpRequest.responseXML. لمزيد من التفاصيل، يرجى قراءة HTML in XMLHttpRequest.
 إذا كنت تستخدم XMLHttpRequest للحصول على صفحة HTML من البعيد، فإن جميع علامات HTML سيتم تخزينها كنصوص في خصائص responseText، مما يجعل التشغيل وتحليل هذه العلامات صعبًا. يوجد ثلاث طرق رئيسية لتحليل علامات HTML هذه:
 1. استخدم خاصية XMLHttpRequest.responseXML.
 2. أدرج المحتوى عبر fragment.body.innerHTML في قطعة وثيقة، ثم استعرض قطعة DOM.
 3. إذا كنت تعرف مسبقًا محتوى وثيقة HTML، يمكنك استخدام RegExp. إذا كانت RegExp التي تستخدمها تتأثر بـ newline characters، قد ترغب في إزالة جميع النسخات من الإشارات النصية. ومع ذلك، فإن هذا الأسلوب هو "آخر وسيلة"، لأنه إذا تم تغيير رمز HTML بسيط، قد تفشل هذه الطريقة. 

معالجة البيانات الثنائية 

على الرغم من أن XMLHttpRequest يُستخدم عادةً لإرسال و استقبال بيانات النص، إلا أنه يمكنه أيضًا إرسال و استقبال محتوى ثنائي. هناك العديد من الطرق التي تم اختبارها جيدًا لاضطلاع XMLHttpRequest بإرسال بيانات ثنائية. استخدام طريقة .overrideMimeType() الخاصة بـ XMLHttpRequest هو إحدى الحلول، رغم أنها ليست طريقة معيارية.

 var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
// استرداد البيانات غير المعالجة كـ string ثنائي
oReq.overrideMimeType("text/plain; charset=x-user-defined");
/* ... */ 

تم إضافة خاصية responseType في معيار XMLHttpRequest Level 2، مما يجعل إرسال و استقبال البيانات الثنائية أسهل.

 var oReq = new XMLHttpRequest();
oReq.onload = function(e) {
 var arraybuffer = xhr.response; // ليس responseText
 /* ... */
}
oReq.open("GET", url, true);
oReq.responseType = "arraybuffer";
oReq.send(); 

استخدام arrays من نوع JavaScript لقبول البيانات الثنائية 

يمكن تغيير نوع البيانات التي يتم استردادها من الخادم عن طريق تعيين خاصية responseType لـ XMLHttpRequest. القيم المتاحة هي سلسلة فارغة (الافتراضية), "arraybuffer", "blob", "document", و "text". سيكون قيمة الخاصية response بناءً على قيمة الخاصية responseType، قد تكون ArrayBuffer، Blob، Document، string، أو NULL (إذا لم يتم إكمال الطلب أو فشله)
 下例读取了一个二进制图像文件,并且由该文件的二进制原生字节创建了一个8位无符号整数的数组。

 var oReq = new XMLHttpRequest();
oReq.open("GET", "/myfile.png", true);
oReq.responseType = "arraybuffer";
oReq.onload = function (oEvent) {
 var arrayBuffer = oReq.response; // 注意:不是oReq.responseText
 if (arrayBuffer) {
  var byteArray = new Uint8Array(arrayBuffer);
  for (var i = 0; i < byteArray.byteLength; i++) {
   // 对数组中的每个字节进行操作
  }
 }
};
oReq.send(null); 

除了上面的方法,还可以使用 BlobBuilder API 直接将arraybuffer数据添加进一个Blob对象中,由于该API还在试验阶段,所以需要加上特定的前缀:

 var BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder || window.BlobBuilder;
var oReq = new XMLHttpRequest();
oReq.open("GET", "/myfile.png", true);
oReq.responseType = "arraybuffer";
oReq.onload = function(oEvent) {
 var blobBuilder = new BlobBuilder();
 blobBuilder.append(oReq.response);
 var blob = blobBuilder.getBlob("image/png");
 // ...
};
oReq.send(); 

在老的浏览器中接受二进制数据
 下面的load_binary_resource()方法可以从指定的URL那里加载二进制数据,并将数据返回给调用者。

 function load_binary_resource(url) {
 var req = new XMLHttpRequest();
 req.open('GET', url, false);
 // خيار charset ثنائي لـ XHR من Marcus Granado 2006 [http://mgran.blogspot.com]
 req.overrideMimeType('text/plain; charset=x-user-defined');
 req.send(null);
 if (req.status != 200) return '';
 return req.responseText;
} 

أكثر العمليات إثارة للإعجاب هي في السطر الخامس، حيث تم تعديل النوع MIME الافتراضي، مما يضطر المتصفح إلى التعامل مع الرد كملف نصي خالٍ من الترجمة باستخدام مجموعة字符 مخصصة. بذلك يُخبر المتصفح بعدم معالجة البيانات وإعادة توجيهها كبايت غير معالج.

 var filestream = load_binary_resource(url);
var abyte = filestream.charCodeAt(x) & 0xff; // إزالة البايت العالي (f7) 

في المثال السابق، تم الحصول على البايت في الموقع x من البيانات الثنائية المعدة للإرسال. نطاق القيم الصالحة هو 0 إلى filestream.length-1.
 للإطلاع على التفاصيل، انظر "استخدام XMLHttpRequest لتحميل الملفات"، لمعرفة كيفية تحميل الملفات.

 إرسال بيانات ثنائية

 تم تعزيز طريقة XMLHttpRequest.send، حيث يمكنك بسهولة إرسال بيانات ثنائية باستخدام ArrayBuffer أو Blob أو File.
 في المثال التالي، تم إنشاء ملف نصي واستخدم طريقة POST لإرسال هذا الملف إلى الخادم. يمكنك أيضًا استخدام أنواع بيانات ثنائية أخرى غير ملف النص.

 var oReq = new XMLHttpRequest();
oReq.open("POST", url, true);
oReq.onload = function (oEvent) {
 // بعد إكمال الرفع.
};
var bb = new BlobBuilder(); // بحاجة إلى المقدمة المناسبة: window.MozBlobBuilder أو window.WebKitBlobBuilder
bb.append('abc123');
oReq.send(bb.getBlob('text/plain')); 

إرسال مصفوفة النوع كبيانات ثنائية
 يمكنك إرسال مصفوفة نوع JavaScript كبيانات ثنائية.

 تعريف myArray = new ArrayBuffer(512);
تعريف longInt8View = new Uint8Array(myArray);
لـ (var i=0; i< longInt8View.length; i++) {
 longInt8View[i] = i % 255;
}
تعريف xhr = new XMLHttpRequest;
xhr.open("POST", url, false);
xhr.send(myArray); 

في المثال السابق تم إنشاء مصفوفة ثمانية بت من 512 حرف وتم إرسالها، بالطبع، يمكنك إرسال أي بيانات ثنائية

 مراقبة التقدم
 يدعم DOM حدث progress لـ XMLHttpRequest النقل، يتبع معيار حدث التقدم Web API: هذه الأحداث تحقق واجهة ProgressEvent.

 var req = new XMLHttpRequest();
// استماع إلى التحميل
req.addEventListener("progress", updateProgress, false);
req.addEventListener("load", transferComplete, false);
req.addEventListener("error", transferFailed, false);
req.addEventListener("abort", transferCanceled, false);
req.open(...);
...
// تقدم في نقل من الخادم إلى العميل (التحميلات)
وظيفة updateProgress(evt) {
 إذا (evt.lengthComputable) {
  تعريف percentComplete = evt.loaded / evt.total;
  ...
 }
  // لا يمكن حساب معلومات التقدم بسبب عدم معرفة حجم الإجمالي
 }
} 

الاحتياط: يجب عليك إضافة استماع إلى الحدث قبل طلب الاتصال بـ open(). وإلا لن يتم إطلاق حدث progress.
 في المثال السابق، تم تحديد حدث progress لتكون معالجته بواسطة دالة updateProgress()، وتم تقديم إجمالي عدد البايتات total والبايتات التي تم رفعها loaded، حيث يمثل total طول البيانات الكلية من عنوان "Content-Length" (بايت). ولكن إذا كان قيمة خاصية lengthComputable هي false، فإن إجمالي عدد البايتات غير معروف ويكون قيمة total 0، إذا كان معروفًا فإن خاصية lengthComputable تكون true
 يحدث حدث progress في تنزيل ورفع البيانات. يتم إطلاق أحداث التنزيل على obj XMLHttpRequest، كما في المثال السابق. يتم إطلاق أحداث الرفع على obj XMLHttpRequest.upload، مثلما يلي:

 var req = new XMLHttpRequest();
//مراقبة التنزيل
req.upload.addEventListener("progress", updateProgress);
req.upload.addEventListener("load", transferComplete);
req.upload.addEventListener("error", transferFailed);
req.upload.addEventListener("abort", transferCanceled);
req.open(); 

ملاحظة: لا يكون حدث progress فعالًا عند استخدام بروتوكول file:.
 يمكن استخدام حدث loadend للكشف عن جميع ثلاثة حالات إنهاء التحميل (abort، load، error):
 req.addEventListener("loadend", loadEnd, false);
 يُلاحظ أنه لا يوجد طريقة يمكن بها معرفة بدقة ما إذا كانت المعلومات التي تتلقاها حدث loadend تأتي من حالة معينة لإنهاء العمل؛ ولكن يمكنك استخدام هذا الحدث لمعالجة جميع حالات انتهاء التحويل. 

يحدث obj XMLHttpRequest أنواع مختلفة من الأحداث في مراحل مختلفة من الطلب، لذا لا يحتاج إلى فحص خاصية.readyState.
 عند استدعاء send ()، يتم إطلاق حدث loadstart الفريد. عند تحميل استجابة الخادم، يحدث حدث progress على obj XMLHttpRequest، عادةً كل 50 ميليسي ثانية تقريبًا، لذا يمكن استخدام هذه الحدثات لتقديم ملاحظات للمستخدم حول تقدم الطلب.
 إذا تم إكمال الطلب بسرعة، قد لا يتم إطلاق حدث progress أبدًا. عند إكمال الحدث، سيتم إطلاق حدث load.
 هناك ثلاثة حالات لا يمكن إنهاء الطلب HTTP، تتطابق مع ثلاثة أحداث. إذا تم تجاوز وقت الاستجابة للطلب، سيتم إطلاق حدث timeout. إذا تم إلغاء الطلب، سيتم إطلاق حدث abort. قد تمنع الأخطاء الشبكية مثل الكثير من التحويلات الإضافية من إكمال الطلب، ولكن في هذه الحالات سيتم إطلاق حدث error.
 لأي طلب محدد، سيقوم المتصفح بتشغيل أحد أحداث load، abort، timeout أو error، بالإضافة إلى الحدث progress.

 if('onprogress' in (new XMLHttpRequest())){ //تحقق من دعم الحدث progress
  var request = new XMLHttpRequest();
  request.onprogress = function (e) {
    if(e.lengthComputable){
      progress.innerHTML = Math.round(100 * e.loaded / e.total) + '\%';
    }
  }
}

هذا هو نهاية محتوى هذا المقال، آمل أن يكون قد ساعدكم في التعلم، وأتمنى أن تدعموا وتعطوا دعمكم لتعليمات النفخ.

البيان: محتويات هذا المقال تم جمعها من الإنترنت، وتحتفظ الملكية للملكيات الأصلية، ويتم جمع المحتويات من قبل المستخدمين عبر الإنترنت الذين يقدمونها بشكل تلقائي، ولا يمتلك هذا الموقع حقوق الملكية، ولا يتم تعديل المحتويات بشكل يدوي، ولا يتحمل الموقع أي مسؤولية قانونية متعلقة بذلك. إذا اكتشفت أي محتوى يشتبه في انتهاك حقوق النسخ، فلا تتردد في إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال #بـ @) لإبلاغنا، وتقديم الدليل على ذلك، وإذا تم التحقق من صحة المعلومات، سيتم حذف المحتوى المزعوم فورًا.

أنت قد تعجبك