मैं एक और समाधान पेश करना चाहता हूं जो कि नोड के बहुत ही मुख्य स्थान पर प्रोग्रामिंग प्रतिमान की गति और दक्षता का उपयोग करता है: घटनाएं।
सब कुछ आप प्रवाह-नियंत्रण का प्रबंधन करने के लिए डिज़ाइन किए गए वादे या मॉड्यूल के साथ कर सकते हैं, जैसे async
, घटनाओं और एक सरल राज्य-मशीन का उपयोग करके पूरा किया जा सकता है, जो मुझे लगता है कि एक पद्धति प्रदान करता है जो, शायद, अन्य विकल्पों की तुलना में समझने में आसान है।
उदाहरण के लिए मान लें कि आप समानांतर में कई फ़ाइलों की लंबाई का योग करना चाहते हैं:
const EventEmitter = require('events').EventEmitter;
// simple event-driven state machine
const sm = new EventEmitter();
// running state
let context={
tasks: 0, // number of total tasks
active: 0, // number of active tasks
results: [] // task results
};
const next = (result) => { // must be called when each task chain completes
if(result) { // preserve result of task chain
context.results.push(result);
}
// decrement the number of running tasks
context.active -= 1;
// when all tasks complete, trigger done state
if(!context.active) {
sm.emit('done');
}
};
// operational states
// start state - initializes context
sm.on('start', (paths) => {
const len=paths.length;
console.log(`start: beginning processing of ${len} paths`);
context.tasks = len; // total number of tasks
context.active = len; // number of active tasks
sm.emit('forEachPath', paths); // go to next state
});
// start processing of each path
sm.on('forEachPath', (paths)=>{
console.log(`forEachPath: starting ${paths.length} process chains`);
paths.forEach((path) => sm.emit('readPath', path));
});
// read contents from path
sm.on('readPath', (path) => {
console.log(` readPath: ${path}`);
fs.readFile(path,(err,buf) => {
if(err) {
sm.emit('error',err);
return;
}
sm.emit('processContent', buf.toString(), path);
});
});
// compute length of path contents
sm.on('processContent', (str, path) => {
console.log(` processContent: ${path}`);
next(str.length);
});
// when processing is complete
sm.on('done', () => {
const total = context.results.reduce((sum,n) => sum + n);
console.log(`The total of ${context.tasks} files is ${total}`);
});
// error state
sm.on('error', (err) => { throw err; });
// ======================================================
// start processing - ok, let's go
// ======================================================
sm.emit('start', ['file1','file2','file3','file4']);
जो आउटपुट देगा:
शुरू: 4 रास्तों का प्रसंस्करण
forEachPath: 4 प्रोसेस चेन शुरू करना
readPath: file1
readPath: file2
processContent: file1
readPath: file3
प्रक्रियासंबंधी: file2
processContent: file3
readPath: file4
processContent: file4
कुल 4 फाइलें 4021 हैं
ध्यान दें कि प्रक्रिया श्रृंखला कार्यों का क्रम सिस्टम लोड पर निर्भर है।
आप कार्यक्रम प्रवाह की कल्पना कर सकते हैं:
start -> forEachPath - + -> readPath 1 -> processContent 1 - + -> किया
+ -> readFile 2 -> प्रक्रियासंपर्क 2 - +
+ -> readFile 3 -> processContent 3 - +
+ -> readFile 4 -> processContent 4 - +
पुन: उपयोग के लिए, विभिन्न प्रवाह नियंत्रण पैटर्न, अर्थात श्रृंखला, समानांतर, बैच, जबकि, जब तक, आदि का समर्थन करने के लिए एक मॉड्यूल बनाना तुच्छ होगा।