প্রথম পার্থক্য - দ্রুত ব্যর্থ
আমি @ zzzzBov এর উত্তরের সাথে একমত, কিন্তু প্রতিশ্রুতির "দ্রুত ব্যর্থ" সুবিধাটি সমস্তই কেবল একটি পার্থক্য নয়। কিছু ব্যবহারকারী মন্তব্য করার সময় কেন প্রতিশ্রুতিটি ব্যবহার করবেন তা জিজ্ঞাসা করেন when যখন এটি কেবল নেতিবাচক দৃশ্যে দ্রুত হয় (যখন কোনও কাজ ব্যর্থ হয়)। আর আমি জিজ্ঞাসা করি কেন? যদি আমার দুটি স্বতন্ত্র এ্যাসিঙ্ক সমান্তরাল কাজ হয় এবং প্রথমটি খুব দীর্ঘ সময়ে সমাধান করা হয় তবে দ্বিতীয়টি খুব অল্প সময়ের মধ্যে প্রত্যাখ্যান করা হয় তবে ব্যবহারকারীরা কেন "খুব অল্প সময়ের" পরিবর্তে ত্রুটি বার্তা "খুব দীর্ঘ সময়" জন্য অপেক্ষা করবেন? বাস্তব জীবনের অ্যাপ্লিকেশনগুলিতে আমাদের অবশ্যই নেতিবাচক দৃশ্য বিবেচনা করতে হবে। তবে ঠিক আছে - এই প্রথম পার্থক্যে আপনি সিদ্ধান্ত নিতে পারবেন কোন বিকল্পটি প্রতিশ্রুতি ব্যবহার করতে হবে all সমস্ত বনাম একাধিক অপেক্ষা it
দ্বিতীয় পার্থক্য - ত্রুটি পরিচালনা
তবে ত্রুটিটি পরিচালনা করার বিষয়ে বিবেচনা করার সময় আপনি অবশ্যই প্রতিশ্রুতি ব্যবহার করুন। একাধিক প্রতীক্ষার সাথে ট্রিগার করা অ্যাসিঙ্ক সমান্তরাল কার্যগুলির ত্রুটিগুলি সঠিকভাবে পরিচালনা করা সম্ভব নয়। নেতিবাচক দৃশ্যে আপনি সর্বদা শেষ হয়ে যাবেন UnhandledPromiseRejectionWarning
এবং PromiseRejectionHandledWarning
আপনি কোথাও চেষ্টা / ধরা ব্যবহার করেন। এজন্য প্রতিশ্রুতি.আল ডিজাইন করা হয়েছিল। অবশ্যই কেউ বলতে পারে যে আমরা ত্রুটিগুলি ব্যবহার করে দমন করতে পারি process.on('unhandledRejection', err => {})
এবং process.on('rejectionHandled', err => {})
এটি ভাল অনুশীলন নয়। আমি ইন্টারনেটে এমন অনেকগুলি উদাহরণ পেয়েছি যা দুটি বা ততোধিক স্বতঃসন্ধিক সমান্তরাল কাজের জন্য ত্রুটি পরিচালনার বিষয়টি মোটেও বিবেচনা করে না বা এটিকে ভুল উপায়ে বিবেচনা করে - কেবল চেষ্টা / ধরা এবং এটি আশা করে ত্রুটি ধরা পড়বে। ভাল অনুশীলন খুঁজে পাওয়া প্রায় অসম্ভব। এজন্য আমি এই উত্তরটি লিখছি।
সারসংক্ষেপ
দুই বা ততোধিক স্বতঃসন্ধিক সমান্তরাল কার্যগুলির জন্য একাধিক প্রতীক্ষা কখনই ব্যবহার করবেন না কারণ আপনি ত্রুটিগুলি গুরুত্ব সহকারে পরিচালনা করতে পারবেন না। এই ব্যবহারের ক্ষেত্রে সর্বদা প্রতিশ্রুতি.আল () ব্যবহার করুন।
আশ্বাস / প্রতীক্ষা প্রতিশ্রুতি প্রতিস্থাপন নয়। প্রতিশ্রুতিগুলি কীভাবে ব্যবহার করবেন এটি কেবল দুর্দান্ত উপায় ... অ্যাসিঙ্ক কোডটি সিঙ্ক স্টাইলে লেখা হয় এবং আমরা then
প্রতিশ্রুতিতে একাধিক এড়াতে পারি ।
কিছু লোক বলেছেন যে প্রতিশ্রুতি। সমস্ত () ব্যবহার করে আমরা কার্য ত্রুটিগুলি পৃথকভাবে পরিচালনা করতে পারি না তবে কেবল প্রথম প্রত্যাখ্যাত প্রতিশ্রুতি থেকে ত্রুটি (হ্যাঁ, কিছু ব্যবহারের ক্ষেত্রে লগিংয়ের জন্য পৃথক হ্যান্ডলিং প্রয়োজন হতে পারে)। এটি সমস্যা নয় - নীচে "সংযোজন" শিরোনাম দেখুন।
উদাহরণ
এই অ্যাসিঙ্ক কার্যটি বিবেচনা করুন ...
const task = function(taskNum, seconds, negativeScenario) {
return new Promise((resolve, reject) => {
setTimeout(_ => {
if (negativeScenario)
reject(new Error('Task ' + taskNum + ' failed!'));
else
resolve('Task ' + taskNum + ' succeed!');
}, seconds * 1000)
});
};
আপনি যখন ইতিবাচক দৃশ্যে কাজ পরিচালনা করেন তখন প্রতিশ্রুতি.আল এবং একাধিক প্রতীক্ষার মধ্যে কোনও পার্থক্য নেই। উভয় উদাহরণ Task 1 succeed! Task 2 succeed!
5 সেকেন্ড পরে শেষ হয় ।
// Promise.all alternative
const run = async function() {
// tasks run immediate in parallel and wait for both results
let [r1, r2] = await Promise.all([
task(1, 5, false),
task(2, 5, false)
]);
console.log(r1 + ' ' + r2);
};
run();
// at 5th sec: Task 1 succeed! Task 2 succeed!
// multiple await alternative
const run = async function() {
// tasks run immediate in parallel
let t1 = task(1, 5, false);
let t2 = task(2, 5, false);
// wait for both results
let r1 = await t1;
let r2 = await t2;
console.log(r1 + ' ' + r2);
};
run();
// at 5th sec: Task 1 succeed! Task 2 succeed!
যখন প্রথম টাস্কটি ইতিবাচক দৃশ্যে 10 সেকেন্ড নেয় এবং সেকেন্ডের কার্যটি নেতিবাচক দৃশ্যে 5 সেকেন্ড সময় নেয় সেখানে ত্রুটি জারি করার ক্ষেত্রে পার্থক্য রয়েছে।
// Promise.all alternative
const run = async function() {
let [r1, r2] = await Promise.all([
task(1, 10, false),
task(2, 5, true)
]);
console.log(r1 + ' ' + r2);
};
run();
// at 5th sec: UnhandledPromiseRejectionWarning: Error: Task 2 failed!
// multiple await alternative
const run = async function() {
let t1 = task(1, 10, false);
let t2 = task(2, 5, true);
let r1 = await t1;
let r2 = await t2;
console.log(r1 + ' ' + r2);
};
run();
// at 5th sec: UnhandledPromiseRejectionWarning: Error: Task 2 failed!
// at 10th sec: PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
// at 10th sec: UnhandledPromiseRejectionWarning: Error: Task 2 failed!
আমাদের ইতিমধ্যে এখানে লক্ষ্য করা উচিত যে সমান্তরালভাবে একাধিক প্রতীক্ষা ব্যবহার করার সময় আমরা কিছু ভুল করছি। অবশ্যই ত্রুটিগুলি এড়াতে আমাদের এটি পরিচালনা করা উচিত! আসুন চেষ্টা করি ...
// Promise.all alternative
const run = async function() {
let [r1, r2] = await Promise.all([
task(1, 10, false),
task(2, 5, true)
]);
console.log(r1 + ' ' + r2);
};
run().catch(err => { console.log('Caught error', err); });
// at 5th sec: Caught error Error: Task 2 failed!
আপনি যেমন সফলভাবে ত্রুটিটি পরিচালনা করতে দেখতে পান আমাদের run
ফাংশনে মাত্র একটি ক্যাচ যুক্ত করতে হবে এবং ক্যাচ লজিক সহ কোড কলব্যাকে রয়েছে ( অ্যাসিঙ্ক স্টাইল )। run
ফাংশনের অভ্যন্তরে আমাদের হ্যান্ডেল ত্রুটির প্রয়োজন নেই কারণ অ্যাসিঙ্ক ফাংশন এটি স্বয়ংক্রিয়ভাবে ঘটে - task
ফাংশন প্রত্যাখ্যানের কারণে run
ফাংশন প্রত্যাখ্যান হয়। কলব্যাক এড়ানোর জন্য আমরা সিঙ্ক শৈলীটি ব্যবহার করতে পারি (async / انتظار / চেষ্টা / চেষ্টা করুন) try { await run(); } catch(err) { }
তবে এই উদাহরণে এটি সম্ভব নয় কারণ আমরা await
মূল থ্রেডে ব্যবহার করতে পারি না - এটি কেবল async ফাংশনে ব্যবহার করা যেতে পারে (এটি যৌক্তিক কারণ কেউই চায় না মূল থ্রেড ব্লক করুন)। হ্যান্ডলিং সিঙ্ক স্টাইলে কাজ করে কিনা তা পরীক্ষা করতে আমরা কল করতে পারিrun
অন্য ASYNC ফাংশন বা ব্যবহার IIFE (অবিলম্বে প্রার্থনা ফাংশন এক্সপ্রেশন) থেকে ফাংশন: (async function() { try { await run(); } catch(err) { console.log('Caught error', err); }; })();
।
এটি কেবলমাত্র দুটি সঠিক সংস্থান সমান্তরাল কাজগুলি পরিচালনা করতে এবং ত্রুটিগুলি পরিচালনা করতে পারে correct আপনার নীচের উদাহরণগুলি এড়ানো উচিত।
// multiple await alternative
const run = async function() {
let t1 = task(1, 10, false);
let t2 = task(2, 5, true);
let r1 = await t1;
let r2 = await t2;
console.log(r1 + ' ' + r2);
};
আমরা বিভিন্ন উপায়ে কোড হ্যান্ডেল করার চেষ্টা করতে পারি ...
try { run(); } catch(err) { console.log('Caught error', err); };
// at 5th sec: UnhandledPromiseRejectionWarning: Error: Task 2 failed!
// at 10th sec: UnhandledPromiseRejectionWarning: Error: Task 2 failed!
// at 10th sec: PromiseRejectionHandledWarning: Promise rejection was handled
... কিছুই ধরা পড়েনি কারণ এটি সিঙ্ক কোডটি পরিচালনা করে তবে run
এটি অ্যাসিঙ্ক
run().catch(err => { console.log('Caught error', err); });
// at 5th sec: UnhandledPromiseRejectionWarning: Error: Task 2 failed!
// at 10th sec: Caught error Error: Task 2 failed!
// at 10th sec: PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
... ডব্লিউটিএফ? আমরা প্রথমত দেখতে পাই যে টাস্ক 2 এর জন্য ত্রুটিটি পরিচালনা করা হয়নি এবং পরে এটি ধরা পড়ে। বিভ্রান্তিকর এবং এখনও কনসোলে ত্রুটি পূর্ণ। এইভাবে ব্যবহারযোগ্য নয়।
(async function() { try { await run(); } catch(err) { console.log('Caught error', err); }; })();
// at 5th sec: UnhandledPromiseRejectionWarning: Error: Task 2 failed!
// at 10th sec: Caught error Error: Task 2 failed!
// at 10th sec: PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
... উপরের মতই ব্যবহারকারী @ কিওয়ার্টি তার মুছে দেওয়া উত্তরে এই অদ্ভুত আচরণ সম্পর্কে জিজ্ঞাসা করেছেন যা ধরা পড়েছে বলে মনে হয় তবে অনাবৃত ত্রুটিগুলিও রয়েছে। আমরা ত্রুটিটি ধরছি কারণ অপেক্ষা (মূলোত্তর) কীওয়ার্ডের সাথে লাইনে রান () প্রত্যাখ্যান করা হয়েছে এবং রান () কল করার সময় ট্র্যাচ / ক্যাচ ব্যবহার করে ক্যাচ করা যায়। আমরা আনহ্যান্ডলড ত্রুটিও পেয়েছি কারণ আমরা অ্যাসিঙ্ক টাস্ক ফাংশনটিকে সিঙ্ক্রোনসিভভাবে কল করছি (কীওয়ার্ডের অপেক্ষা না করে) এবং এই টাস্কটি রান () ফাংশনের বাইরে চলে এবং বাইরেও ব্যর্থ হয়। এটি একই রকম হয় যখন সেট টাইমআউটটিতে কোডের কোন অংশটি চালিত হয় এমন কোনও সিঙ্ক ফাংশন কল করার সময় আমরা চেষ্টা / ধরার মাধ্যমে ত্রুটি পরিচালনা করতে সক্ষম হই না function test() { setTimeout(function() { console.log(causesError); }, 0); }; try { test(); } catch(e) { /* this will never catch error */ }
।
const run = async function() {
try {
let t1 = task(1, 10, false);
let t2 = task(2, 5, true);
let r1 = await t1;
let r2 = await t2;
}
catch (err) {
return new Error(err);
}
console.log(r1 + ' ' + r2);
};
run().catch(err => { console.log('Caught error', err); });
// at 5th sec: UnhandledPromiseRejectionWarning: Error: Task 2 failed!
// at 10th sec: PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
... "কেবল" দুটি ত্রুটি (তৃতীয়টি অনুপস্থিত) তবে কিছুই ধরা পড়েনি।
সংযোজন (পৃথকভাবে কার্য ত্রুটিগুলি পরিচালনা করুন এবং প্রথম ব্যর্থ ত্রুটিও হ্যান্ডেল করুন)
const run = async function() {
let [r1, r2] = await Promise.all([
task(1, 10, true).catch(err => { console.log('Task 1 failed!'); throw err; }),
task(2, 5, true).catch(err => { console.log('Task 2 failed!'); throw err; })
]);
console.log(r1 + ' ' + r2);
};
run().catch(err => { console.log('Run failed (does not matter which task)!'); });
// at 5th sec: Task 2 failed!
// at 5th sec: Run failed (does not matter which task)!
// at 10th sec: Task 1 failed!
... নোট করুন যে এই উদাহরণে আমি নেগেটিভ সেনেরিও = সত্যই ব্যবহার করেছি উভয় কাজের জন্য আরও ভাল প্রদর্শনের জন্য যা ঘটে ( throw err
চূড়ান্ত ত্রুটি থেকে আগুনে ব্যবহৃত হয়)