stream - خطأ في التعامل مع تدفقات node.js




(5)

ما الطريقة الصحيحة للتعامل مع الأخطاء مع مجموعات البث؟ أعلم بالفعل أن هناك حدث "خطأ" يمكنك الاستماع إليه ، لكنني أريد معرفة المزيد من التفاصيل حول الحالات المعقدة بشكل تعسفي.

بالنسبة للمبتدئين ، ماذا تفعل عندما تريد القيام بسلسلة أنابيب بسيطة:

input.pipe(transformA).pipe(transformB).pipe(transformC)...

وكيف يمكنك إنشاء أحد هذه التحويلات بشكل صحيح حتى يتم التعامل مع الأخطاء بشكل صحيح؟

المزيد من الأسئلة ذات الصلة:

  • عندما يحدث خطأ ما ، ماذا يحدث لحدث "النهاية"؟ هل لا تطلق؟ هل تطلق في بعض الأحيان؟ هل يعتمد على التحويل / التيار؟ ما هي المعايير هنا؟
  • هل هناك أي آليات لنشر الأخطاء من خلال الأنابيب؟
  • هل النطاقات تحل هذه المشكلة بفاعلية؟ الأمثلة ستكون لطيفة.
  • هل الأخطاء التي تخرج من أحداث "الخطأ" لها آثار كومة؟ بعض الأحيان؟ أبدا؟ هل هناك طريقة للحصول على واحد منهم؟

Answers

تحول

إن تيارات التحويل قابلة للقراءة والكتابة ، وبالتالي فهي تيارات "وسطية" جيدة. لهذا السبب يتم الإشارة إليها أحيانًا على أنها من through البث. وهي تشبه البخار المزدوج بهذه الطريقة ، إلا أنها توفر واجهة جميلة للتلاعب بالبيانات بدلاً من إرسالها فقط. الغرض من دفق التحويل هو التلاعب في البيانات كما هي عبر الأنابيب. قد ترغب في إجراء بعض المكالمات غير المتزامنة على سبيل المثال ، أو اشتقاق اثنين من الحقول ، أو إعادة رسم بعض الأشياء ، إلخ.

لمعرفة كيفية إنشاء تيار تحويل ، انظر here here . كل ما عليك القيام به هو :

  1. تشمل وحدة دفق
  2. إنشاء (أو ترث من) فئة تحويل
  3. تنفيذ طريقة _transform والتي تأخذ (chunk, encoding, callback) .

القطعة هي بياناتك. معظم الوقت لن تحتاج إلى القلق بشأن الترميز إذا كنت تعمل في objectMode = true . يتم استدعاء رد الاتصال عند الانتهاء من معالجة القطعة. ثم يتم دفع هذه القطعة إلى الدفق القادم.

إذا كنت تريد وحدة المساعد لطيفة من شأنها أن تمكنك من القيام به من خلال تيار حقا بسهولة ، أقترح خلال 2.

للتعامل مع الخطأ ، والحفاظ على القراءة.

يضخ

في سلسلة الأنابيب ، فإن أخطاء المناولة ليست في الواقع بسيطة. استناداً إلى مؤشر الترابط هذا ، لا يتم إنشاء .pipe () لإعادة توجيه الأخطاء. شيء من هذا القبيل ...

var a = createStream();
a.pipe(b).pipe(c).on('error', function(e){handleError(e)});

... سوف يستمع فقط للأخطاء في الدفق c . إذا تم إصدار حدث خطأ على ، لن يتم تمرير ذلك إلى أسفل ، وفي الواقع ، من شأنه أن يلقي. للقيام بذلك بشكل صحيح:

var a = createStream();
a.on('error', function(e){handleError(e)})
.pipe(b)
.on('error', function(e){handleError(e)})
.pipe(c)
.on('error', function(e){handleError(e)});

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

إحدى المكتبات التي أجدها مفيدة على الرغم من أنك إذا كنت تعاني من حالة لا تريد فيها سوى التقاط الأخطاء في الوجهة وكنت لا تهتم كثيرًا بمكان حدوث event-stream .

النهاية

عند تشغيل حدث خطأ ، لن يتم تشغيل الحدث النهائي (بشكل صريح). سيؤدي بث حدث خطأ إلى إنهاء البث.

المجالات

من واقع خبرتي ، تعمل النطاقات بشكل جيد في معظم الأوقات. إذا كان لديك حدث خطأ لم تتم معالجته (أي أنه يصدر خطأ على دفق بدون مستمع) ، فيمكن أن يتعطل الخادم. الآن ، كما تشير المقالة أعلاه ، يمكنك لف دفق في مجال الذي يجب أن يلتقط جميع الأخطاء بشكل صحيح.

var d = domain.create();
 d.on('error', handleAllErrors);
 d.run(function() {
     fs.createReadStream(tarball)
       .pipe(gzip.Gunzip())
       .pipe(tar.Extract({ path: targetPath }))
       .on('close', cb);
 });

جمال المجالات هو أنها ستحافظ على تتبعات المكدس. على الرغم من أن الحدث-تيار يقوم بعمل جيد لهذا أيضا.

لمزيد من القراءة ، اطلع على stream-handbook . جميلة في العمق ، ولكن فائقة مفيدة وتعطي بعض الروابط الرائعة للكثير من وحدات مفيدة.


النطاقات موقوفة. لا تحتاج لهم.

لهذا السؤال ، التمييز بين التحويل أو للكتابة ليست مهمة جدا.

إجابة mshell_lauren رائعة ، ولكن كبديل يمكنك أيضًا الاستماع صراحةً إلى حدث الخطأ في كل دفق تعتقد أنه قد يكون خطأ. وإعادة استخدام وظيفة المعالج إذا كنت تفضل ذلك.

var a = createReadableStream()
var b = anotherTypeOfStream()
var c = createWriteStream()

a.on('error', handler)
b.on('error', handler)
c.on('error', handler)

a.pipe(b).pipe(c)

function handler (err) { console.log(err) }

يؤدي ذلك إلى منع الاستثناء غير المشهور الشائع إذا كان أحد تلك الأحداث يطلق حدث الخطأ الخاص به


يمكن نشر الأخطاء من السلسلة بأكملها إلى تيار أقصى اليمين باستخدام وظيفة بسيطة:

function safePipe (readable, transforms) {
    while (transforms.length > 0) {
        var new_readable = transforms.shift();
        readable.on("error", function(e) { new_readable.emit("error", e); });
        readable.pipe(new_readable);
        readable = new_readable;
    }
    return readable;
}

والتي يمكن استخدامها مثل:

safePipe(readable, [ transform1, transform2, ... ]);

استخدم نمط Node.js بإنشاء ميكانيكا دفق التحويل واستدعاء معاودة الاتصال done مع وسيطة من أجل نشر الخطأ:

var transformStream1 = new stream.Transform(/*{objectMode: true}*/);

transformStream1.prototype._transform = function (chunk, encoding, done) {
  //var stream = this;

  try {
    // Do your transform code
    /* ... */
  } catch (error) {
    // nodejs style for propagating an error
    return done(error);
  }

  // Here, everything went well
  done();
}

// Let's use the transform stream, assuming `someReadStream`
// and `someWriteStream` have been defined before
someReadStream
  .pipe(transformStream1)
  .on('error', function (error) {
    console.error('Error in transformStream1:');
    console.error(error);
    process.exit(-1);
   })
  .pipe(someWriteStream)
  .on('close', function () {
    console.log('OK.');
    process.exit();
  })
  .on('error', function (error) {
    console.error(error);
    process.exit(-1);
   });

var http = require('http');
var fs = require('fs');
var index = fs.readFileSync('index.html');

http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'html'});
res.end(index);
}).listen(9615);

//Just Change The CONTENT TYPE to 'html'




node.js stream