مقدمة
أكبر أبرز ما في NodeJS هو نموذج I/O غير المحظور ، والذي يجعل Nodejs لديها قدرات معالجة تزامن قوية وهي مناسبة للغاية لكتابة تطبيقات الشبكة. معظم عمليات الإدخال/الإخراج في NodeJs غير متزامنة تقريبًا ، أي أن نتائج عمليات الإدخال/الإخراج الخاصة بنا تحتاج إلى معالجة في وظيفة رد الاتصال ، مثل الوظيفة التالية التي تقرأ محتوى الملف:
نسخة الكود كما يلي:
fs.readfile ('/etc/passwd' ، الدالة (err ، البيانات) {
إذا (خطأ) رمي خطأ ؛
console.log (البيانات) ؛
}) ؛
لذا ، ما الذي يجب أن نفعله إذا قرأنا ملفين وندمج محتويات هذين الملفان معًا؟ قد يقوم معظم الأشخاص الذين ليسوا على اتصال بـ JS القيام بذلك:
نسخة الكود كما يلي:
fs.readfile ('/etc/passwd' ، الدالة (err ، البيانات) {
إذا (خطأ) رمي خطأ ؛
fs.readfile ('/etc/passwd2' ، الدالة (err ، data2) {
إذا (خطأ) رمي خطأ ؛
// معالجة بيانات البيانات والبيانات 2 هنا
}) ؛
}) ؛
إذا تعاملت مع سيناريوهات مماثلة متعددة ، ألا تكون وظائف رد الاتصال هي طبقة متداخلة؟ هذا هو ما يسميه الناس في كثير من الأحيان هرم أو جحيم رد الاتصال (http://callbackhell.com/) ، وهي أيضًا المشكلة الأكثر إزعاجًا لـ JS Novice.
لقد جلب هذا النوع من الكود المتداخل العديد من المشاكل إلى التنمية ، ينعكس بشكل أساسي في:
1. إن إمكانية الكود تصبح أسوأ
2. تصحيح الصعوبات
3. من الصعب التحقق بعد حدوث استثناء
تقدم هذه المقالة بشكل أساسي كيفية التعامل مع مشكلات رد الاتصال غير المتزامنة أعلاه بأناقة.
الحل الأساسي: معالجة عمليات الاسترداد غير المتزامنة بشكل متكرر
يمكننا استخدام العودية كأداة التحكم في التنفيذ للرمز. قم بتغليف العمليات التي يجب تنفيذها في وظيفة ، والتحكم في عملية تنفيذ الكود عن طريق الاتصال بشكل متكرر في وظيفة رد الاتصال. بدون مزيد من اللغط ، دعنا نتحدث عن الهراء ، دعنا نلقي نظرة على الكود السابق:
نسخة الكود كما يلي:
var fs = require ('fs') ؛
// قائمة الملفات المراد معالجتها
files var = ['file1' ، 'file2' ، 'file3'] ؛
وظيفة parsefile () {
if (files.length == 0) {
يعود؛
}
var file = files.shift () ؛
fs.readfile (ملف ، وظيفة (err ، البيانات) {
// معالجة بيانات الملف هنا
parsefile () ؛ // بعد المعالجة ، قم بمعالجة الملف التالي من خلال المكالمة العودية
}) ؛
}
// ابدأ في المعالجة
parsefile () ؛
قام الرمز أعلاه بمعالجة الملفات الموجودة في الصفيف بدورها كمثال ، حيث قدمت عملية تنفيذ التحكم في الكود من خلال الوسائل العودية.
من الجيد تطبيقه على بعض السيناريوهات البسيطة ، مثل: يمكننا استخدام هذه الطريقة عن طريق حفظ البيانات في صفيف في قاعدة البيانات بدورها.
بشكل متكرر ، يمكن حل بعض مشاكل رد الاتصال غير المتزامنة البسيطة. ومع ذلك ، لا يزال يبدو عاجزًا عن التعامل مع عمليات الاسترجاعات غير المتزامنة المعقدة (مثل مزامنة نتائج العمليات غير المتزامنة المتعددة).
نقطة رائعة: استخدم مكتبات طرف ثالث مثل Async ، Q ،
من أجل التعامل بشكل أفضل مع عمليات الاسترداد المتداخلة ، يمكنك التفكير في استخدام بعض مكتبات الطرف الثالث التي تتعامل بشكل خاص مع غير متزامن. بالطبع ، إذا كان لديك القدرة ، فيمكنك كتابة أداة مساعدة للمعالجة غير المتزامنة بنفسك.
المكتبات الأكثر استخدامًا للتعامل مع المعالجة غير المتزامنة هي: Async ، Q و Promise. انطلاقًا من موقع NPMJS.org ، فإن Async هو الأكثر شعبية. لقد استخدمت Async من قبل ، وهي بالفعل مريحة للغاية ، ويتم تنفيذ تدفقات التحكم في المعالجة غير المتزامنة المختلفة بشكل جيد.
سنستخدم ASYNC لمعالجة الكود الذي يقرأ في البداية ملفين في نفس الوقت ، كما هو موضح أدناه:
نسخة الكود كما يلي:
var async = طلب ('async')
، fs = يحتاج ('fs') ؛
Async.paralled ([[
وظيفة (رد الاتصال) {
fs.readfile ('/etc/passwd' ، الدالة (err ، البيانات) {
إذا (خطأ) رد الاتصال (err) ؛
رد الاتصال (NULL ، البيانات) ؛
}) ؛
} ،
وظيفة (رد الاتصال) {
fs.readfile ('/etc/passwd2' ، الدالة (err ، data2) {
إذا (خطأ) رد الاتصال (err) ؛
رد الاتصال (NULL ، Data2) ؛
}) ؛
}
]
وظيفة (خطأ ، النتائج) {
// معالجة بيانات البيانات والبيانات 2 هنا ، ويتم الحصول على محتوى كل ملف من النتائج
}) ؛
من خلال وحدة ASYNC ، يمكن التحكم في عملية التنفيذ غير المتزامنة جيدًا ، والتي يمكن أن تحل أيضًا مشكلة عمليات الاسترجاعات ذات الطبقات. الكود أكثر وضوحًا من ذي قبل ، لكن لا يزال لا يمكن فصله عن وظيفة رد الاتصال.
فكر في الأمر ، سيكون من الرائع أن تتمكن من التعامل مع غير متزامن دون استخدام وظائف رد الاتصال. بعد ذلك ، دعنا نتحدث عن استخدام الميزات الجديدة لـ ES6 لتحقيق هذا الهدف.
نقطة أنيقة: احتضان ES6 ، واستبدل وظائف رد الاتصال ، وحل مشكلة جحيم رد الاتصال
بالمناسبة ، قدم ECMASCRIPT Harmony (ES6) الكثير من الميزات الجديدة إلى JS. يمكن للطلاب الذين لا يعرفون الكثير عن ES6 إلقاء نظرة على Baidu بمفردهم.
لاستخدام الميزات الجديدة لـ ES6 في NodeJS ، تحتاج إلى استخدام v0.11.x أو أعلى.
تقدم هذه المقالة استخدام ميزة المولد بدلاً من وظائف رد الاتصال. لا أعرف عن المولد؟ يمكنك التحقق من ذلك هنا.
هنا نستخدم وحدتين Co و Thunkify ، ونحن نستخدم الأمر NPM تثبيت لتثبيته.
خذ المشكلة المذكورة في بداية هذه المقالة كمثال. رمز المثال باستخدام ميزة المولد كما يلي:
نسخة الكود كما يلي:
var fs = require ('fs')
، co = طلب ('co')
، thunkify = طلب ('thunkify') ؛
var readfile = thunkify (fs.readfile) ؛
CO (function *() {
var test1 = rendfile العائد ('test1.txt') ؛
var test2 = rendfile العائد ('test2.txt') ؛
var test = test1.toString () + test2.toString () ؛
console.log (اختبار) ؛
}) () ؛
من السهل جدًا التعامل مع الاستثناءات في الكود ، فقط قم بذلك على هذا النحو:
نسخة الكود كما يلي:
يحاول {
var test1 = rendfile العائد ('test1.txt') ؛
} catch (e) {
// التعامل مع الاستثناءات هنا
}
هل هذا النوع من الكود أكثر أناقة؟ أليس من الرائع التعامل مع غير متزامن مثل كتابة التعليمات البرمجية المتزامنة؟
الإطار الأكثر شعبية لتطوير الويب في حقل NodeJS هو Express. تجدر الإشارة إلى أن العضو الأساسي في Express TJ ، The Great Master of Express ، قاد إطارًا جديدًا على شبكة الإنترنت - KOA ، الذي يدعي أنه الجيل القادم من إطار تطوير الويب. يستخدم KOA حقًا ميزة Generator ES6 لمساعدتنا في تجنب الوقوع في طبقات من عمليات الاسترجاعات عند تطوير نظام الويب.
لخص
اقتبس جملة من ترويج مشروع FIBJS: أقل رد الاتصال ، المزيد من الفتيات - أقل من عمليات الاسترجاعات ، المزيد من الفتيات