নোড.জেএস স্ট্রিমগুলির সাথে পরিচালনা করতে ত্রুটি


164

স্ট্রিমগুলির সাথে ত্রুটিগুলি হ্যান্ডেল করার সঠিক উপায় কী? আমি ইতিমধ্যে জানি যে একটি 'ত্রুটি' ইভেন্ট রয়েছে যা আপনি শুনতে পারবেন, তবে আমি নির্বিচারে জটিল পরিস্থিতি সম্পর্কে আরও কিছু বিশদ জানতে চাই।

প্রারম্ভিকদের জন্য, আপনি যখন সাধারণ পাইপ চেইন করতে চান তখন আপনি কী করবেন:

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

এবং কীভাবে আপনি সেই রূপান্তরগুলির মধ্যে একটি সঠিকভাবে তৈরি করবেন যাতে ত্রুটিগুলি সঠিকভাবে পরিচালিত হয়?

আরও সম্পর্কিত প্রশ্ন:

  • যখন কোনও ত্রুটি ঘটে, তখন 'শেষ' ইভেন্টের কী ঘটে? এটি কি কখনও বরখাস্ত হয় না? এটি কখনও কখনও বরখাস্ত হয়? এটি কি রূপান্তর / প্রবাহের উপর নির্ভর করে? এখানে মান কি?
  • পাইপগুলির মাধ্যমে ত্রুটির প্রস্তাব দেওয়ার কোনও ব্যবস্থা আছে কি?
  • ডোমেনগুলি কার্যকরভাবে এই সমস্যাটি সমাধান করে? উদাহরণগুলি সুন্দর হবে।
  • 'ত্রুটি' ইভেন্টগুলি থেকে বেরিয়ে আসা ত্রুটিগুলি কি স্ট্যাকের চিহ্ন রয়েছে? কখনও কখনও? কখনো? তাদের কাছ থেকে একটি পাওয়ার উপায় আছে?

1
এটি তুচ্ছ নয়। Promiseফ্রেমওয়ার্কগুলি এটিকে অনেক সহজ করে
তোলে

27
দুর্ভাগ্যক্রমে প্রতিশ্রুতি / ফিউচারগুলি সত্যই স্ট্রিমগুলিতে আপনাকে সহায়তা করতে পারে না ...
বিটি

উত্তর:


222

রুপান্তর

রূপান্তর স্ট্রিমগুলি উভয়ই পঠনযোগ্য এবং লিখনযোগ্য এবং এইভাবে সত্যিই ভাল 'মাঝারি' স্ট্রিম রয়েছে। এই কারণে, তাদের কখনও কখনও throughস্ট্রিম হিসাবে উল্লেখ করা হয়। তারা এইভাবে একটি দ্বৈত প্রবাহের অনুরূপ, কেবলমাত্র কেবল এটির মাধ্যমে প্রেরণ না করে ডেটা ম্যানিপুলেট করার জন্য একটি দুর্দান্ত ইন্টারফেস সরবরাহ করে। রূপান্তর স্ট্রিমের উদ্দেশ্য হ'ল তথ্যটি স্ট্রিমের মধ্য দিয়ে পাইপ করায় হেরফের করা। আপনি কিছু অ্যাসিঙ্ক কল করতে চাইতে পারেন, উদাহরণস্বরূপ, বা কয়েকটি ক্ষেত্র নেওয়া, কিছু জিনিস পুনর্নির্মাণ করা ইত্যাদি


যেখানে আপনি একটি রূপান্তর প্রবাহ রাখতে পারেন


কীভাবে একটি রূপান্তর স্ট্রিম তৈরি করতে হয় তা এখানে এবং এখানে দেখুন । আপনাকে যা করতে হবে তা হ'ল:

  1. স্ট্রিম মডিউলটি অন্তর্ভুক্ত করুন
  2. রূপান্তর বর্গ ইনস্ট্যান্টিয়েট (বা উত্তরাধিকারসূত্রে)
  3. একটি _transformপদ্ধতি প্রয়োগ করে যা গ্রহণ করে a (chunk, encoding, callback)

খণ্ডটি হ'ল আপনার ডেটা। আপনি যদি কাজ করে থাকেন তবে বেশিরভাগ সময় আপনাকে এনকোডিং সম্পর্কে চিন্তা করতে হবে না objectMode = true। কলঙ্কব্যাকটি ডাকা হয় যখন আপনি খণ্ডটি প্রক্রিয়াজাতকরণ শেষ করেন। এই অংশটিকে পরবর্তী স্ট্রিমের দিকে ঠেলে দেওয়া হয়।

আপনি যদি এমন কোনও দুর্দান্ত সহায়ক মডিউল চান যা আপনাকে সত্যই সহজেই প্রবাহের মাধ্যমে করতে সক্ষম করে, আমি পরামর্শ দিয়েছি 2

ত্রুটি পরিচালনা করার জন্য, পড়া চালিয়ে যান।

নল

একটি পাইপ চেইনে, হ্যান্ডলিং ত্রুটিগুলি আসলে তুচ্ছ নয়। এই থ্রেড অনুসারে। পাইপ () ত্রুটিগুলি ফরোয়ার্ড করার জন্য নির্মিত হয় না। এরকম কিছু ...

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

... কেবল স্ট্রিমের ত্রুটিগুলি শুনবে c। যদি কোনও ত্রুটির ঘটনাটি নির্গত হয় a, তবে এটি পাস হবে না এবং প্রকৃতপক্ষে নিক্ষেপ করবে। এটি সঠিকভাবে করতে:

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)});

এখন, যদিও দ্বিতীয় উপায়টি আরও ভার্বোজ, আপনি কমপক্ষে আপনার ত্রুটিগুলি কোথায় ঘটবে সে প্রসঙ্গে রাখতে পারেন। এটি সাধারণত একটি ভাল জিনিস।

এক গ্রন্থাগার আমি সহায়ক যদিও এটি আপনি একটি কেস আছে যেখানে আপনি শুধুমাত্র গন্তব্যে ত্রুটি ক্যাপচার করতে চান এবং আপনি এত সম্পর্কে যেখানে এটা ঘটেছে গ্রাহ্য না হয় না ঘটনা-স্ট্রীম

শেষ

যখন কোনও ত্রুটি ইভেন্টটি বরখাস্ত করা হয়, শেষ ইভেন্টটি বহিস্কার করা হবে না (স্পষ্টভাবে)। ত্রুটি ইভেন্টের নির্গমন প্রবাহকে শেষ করবে।

ডোমেইনের

আমার অভিজ্ঞতায়, ডোমেনগুলি বেশিরভাগ সময় সত্যই ভাল কাজ করে। আপনার যদি একটি অপ্রচলিত ত্রুটি ইভেন্ট থাকে (অর্থাত শ্রোতা ব্যতীত কোনও স্ট্রিমে ত্রুটি নির্গত করে), সার্ভারটি ক্রাশ করতে পারে। এখন, উপরোক্ত নিবন্ধটি হিসাবে উল্লেখ করা হয়েছে, আপনি কোনও ডোমেনে স্ট্রিমটি মোড়ানো করতে পারেন যা সমস্ত ত্রুটি সঠিকভাবে ধরা উচিত।

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);
 });

ডোমেনগুলির সৌন্দর্য হ'ল তারা স্ট্যাকের চিহ্নগুলি সংরক্ষণ করবে। যদিও ইভেন্ট-স্ট্রিম এটির একটি ভাল কাজ করে।

আরও পড়ার জন্য, স্ট্রিম-হ্যান্ডবুকটি দেখুন । গভীরতায় অত্যন্ত, তবে সুপার দরকারী এবং প্রচুর সহায়ক মডিউলগুলিতে কিছু দুর্দান্ত লিঙ্ক দেয়।


এটা সত্যিই দুর্দান্ত তথ্য, ধন্যবাদ! আপনি কেন একটি রূপান্তর প্রবাহ তৈরি করতে চান এবং কেন এটি আমার প্রশ্নের সাথে সম্পর্কিত সে সম্পর্কে আপনি কিছুটা যুক্ত করতে পারেন?
বিটি

অবশ্যই - যদিও আপনি এটি সম্পর্কে জিজ্ঞাসা করেছেন আমি এটি সম্পর্কিত অনুধাবন করেছি; )
মিশেল_লাউরেন

1
গুগল গ্রুপস-নোডজেসগুলিতে এই পোস্ট করুন: নোডজেস : গ্রুপ. google.com/d/msg/nodejs/lJYT9hZxFu0/L59CFbqWGyYJ (গ্রুকবেস নয়)
jpillora

এই উত্তর নিখুঁতভাবে লেখা হয়। আমি ডোমেন পরামর্শটি তদন্ত করতে যাচ্ছি - এটি এমন ধরণের সমাধান যা আমি সন্ধান করছিলাম বলে মনে হচ্ছে।
সেমিকোলন

12
নোট করুন যে আপনাকে .on('error')কোনও বেনামি কার্যক্রমে হ্যান্ডলারটি মোড়ানোর দরকার নেই, a.on('error', function(e){handleError(e)})a.on('error', handleError)
যেমনটি

28

আপনি যদি নোড> = v10.0.0 ব্যবহার করে থাকেন তবে আপনি স্ট্রিম.পাইপলাইন এবং স্ট্রিম.ফিনিশড ব্যবহার করতে পারেন ।

উদাহরণ স্বরূপ:

const { pipeline, finished } = require('stream');

pipeline(
  input, 
  transformA, 
  transformB, 
  transformC, 
  (err) => {
    if (err) {
      console.error('Pipeline failed', err);
    } else {
      console.log('Pipeline succeeded');
    }
});


finished(input, (err) => {
  if (err) {
    console.error('Stream failed', err);
  } else {
    console.log('Stream is done reading');
  }
});

আরও আলোচনার জন্য এই গিথুব পিআর দেখুন।


1
কেন তুমি ব্যবহার করেন finished, যদিও যখন pipelineইতিমধ্যে একটি কলব্যাক আছে?
মার্কোস পেরেইরা

4
আপনি পাইপলাইন এবং পৃথক স্ট্রিমের মধ্যে ত্রুটিগুলি আলাদাভাবে পরিচালনা করতে চাইতে পারেন।
শুসন

25

ডোমেনগুলি হ্রাস করা হয়। আপনার তাদের দরকার নেই

এই প্রশ্নের জন্য, রূপান্তরকারী বা লেখার যোগ্যতার মধ্যে পার্থক্য এত গুরুত্বপূর্ণ নয়।

মিশেল_লাউরেনের উত্তর দুর্দান্ত, তবে বিকল্প হিসাবে আপনি প্রতিটি স্ট্রিমের ত্রুটি ইভেন্টটি স্পষ্টভাবে শুনতে পারবেন বলে মনে করেন যে ত্রুটি হতে পারে। এবং আপনি যদি চান তবে হ্যান্ডলারের ফাংশনটি পুনরায় ব্যবহার করুন।

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) }

এমনটি করা কুখ্যাত কমন ব্যতিক্রমকে প্রতিরোধ করে those


3
3 টি ভিন্ন ভিন্ন ত্রুটির ইভেন্টগুলি পরিচালনা করতে মজা পাবেন এবং প্রার্থনা করুন যে 3 টি ভিন্ন স্ট্রিমিং লিব লিখেছেন তিনি সঠিকভাবে ত্রুটি পরিচালনা করতে ভুল প্রয়োগ করেছেন
আলেকজান্ডার মিলস

4
@ অ্যালেক্স মিলস 1) 3 টি ইভেন্ট হ্যান্ডেল করতে সমস্যা কি এবং কেন তারা "আলাদা" হয়, যখন তাদের ধরণ একই রকম হয় - errorতবে প্রতিটি ঘটনা পৃথক হওয়ার বিষয়টি নিয়ে মীমাংসা করতে পারে; ২) নেটিড.জেএস এর কার্যকারিতা ব্যতীত উপরে কোন স্ট্রিমিং লিবস লেখা আছে? এবং 3) কেন তারা ঘটনাগুলিকে অভ্যন্তরীণভাবে পরিচালনা করে তা কেন গুরুত্বপূর্ণ, যখন এটি স্পষ্টতই কাউকে ইতিমধ্যে যা কিছু আছে তার উপরে অতিরিক্ত ত্রুটি হ্যান্ডলার সংযুক্ত করার অনুমতি দেয়?
amn

10

একটি সম্পূর্ণ ফাংশন ব্যবহার করে পুরো চেইন থেকে ত্রুটিগুলি ডানদিকের প্রবাহে প্রচার করা যেতে পারে:

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, ... ]);

5

.on("error", handler)কেবল স্ট্রিম ত্রুটির যত্ন নেয় তবে আপনি যদি কাস্টম ট্রান্সফর্ম স্ট্রিম ব্যবহার করছেন তবে ফাংশনটির .on("error", handler)ভিতরে ঘটে যাওয়া ত্রুটিগুলি ধরবেন না _transform। সুতরাং অ্যাপ্লিকেশন প্রবাহ নিয়ন্ত্রণের জন্য কেউ এর মতো কিছু করতে পারে: -

this_transformফাংশনে কীওয়ার্ডটি Streamনিজেকে বোঝায় , যা একটি EventEmitter। সুতরাং আপনি try catchত্রুটিগুলি ধরতে নীচের মত ব্যবহার করতে পারেন এবং পরে তা কাস্টম ইভেন্ট হ্যান্ডলারের কাছে প্রেরণ করুন।

// CustomTransform.js
CustomTransformStream.prototype._transform = function (data, enc, done) {
  var stream = this
  try {
    // Do your transform code
  } catch (e) {
    // Now based on the error type, with an if or switch statement
    stream.emit("CTError1", e)
    stream.emit("CTError2", e)
  }
  done()
}

// StreamImplementation.js
someReadStream
  .pipe(CustomTransformStream)
  .on("CTError1", function (e) { console.log(e) })
  .on("CTError2", function (e) { /*Lets do something else*/ })
  .pipe(someWriteStream)

এইভাবে, আপনি আপনার যুক্তি এবং ত্রুটি হ্যান্ডলার পৃথক রাখতে পারেন। এছাড়াও, আপনি কেবল কিছু ত্রুটিগুলি পরিচালনা করতে এবং অন্যকে উপেক্ষা করতে পারেন।


বিকল্প আপডেট : আরএক্সজেএস পর্যবেক্ষণযোগ্য


4

এক দ্বৈত স্ট্রিমের সাথে বেশ কয়েকটি স্ট্রিম সংযুক্ত করতে মাল্টিপাইপ প্যাকেজ ব্যবহার করুন । এবং এক জায়গায় ত্রুটিগুলি পরিচালনা করুন।

const pipe = require('multipipe')

// pipe streams
const stream = pipe(streamA, streamB, streamC) 


// centralized error handling
stream.on('error', fn)

1

ট্রান্সফর্ম স্ট্রিম মেকানিক্স তৈরি করে এবং 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);
   });

হুম, তাই আপনি যদি বলছেন যে সমস্ত স্ট্রিম প্রসেসরগুলি এভাবে নির্মিত হয়েছিল, ত্রুটিগুলি প্রচার করবে?
বিটি

-2

ধরার চেষ্টা করুন স্ট্রিমের মধ্যে থাকা ত্রুটিগুলি ক্যাপচার করবে না কারণ কলিং কোডটি ইতিমধ্যে বের হয়ে যাওয়ার পরে এগুলি ফেলে দেওয়া হয়েছে। আপনি ডকুমেন্টেশন উল্লেখ করতে পারেন:

https://nodejs.org/dist/latest-v10.x/docs/api/errors.html


ধন্যবাদ, তবে এটি প্রশ্নের কোনও উত্তর দেয় না।
বিটি

আমাকে 40 পৃষ্ঠার নথিটি দেওয়া কার্যকর নয়। আপনি কি মনে করেন যে সেই দৈত্য পৃষ্ঠায় আমার কী উল্লেখ করা উচিত? এছাড়াও, আপনি আমার প্রশ্ন পড়েছেন? আমার প্রশ্নটি "এই প্রবাহের সাথে কাজ করার চেষ্টা করে না?" আমি ইতিমধ্যে ভালোভাবেই অবগত রয়েছি যে ট্রাই-ক্যাচ অ্যাসিক্রোনাস ত্রুটিগুলি যেমন স্ট্রিম প্রসেসিং পাইপলাইনগুলি থেকে কাজ করে না।
বিটি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.