ওয়েব অ্যাপ্লিকেশানগুলিতে ডিবাগিং ব্যতিক্রমগুলি সহজ বলে মনে হয়: কিছু ভুল হয়ে গেলে এক্সিকিউশন থামান এবং তদন্ত করুন। কিন্তু জাভাস্ক্রিপ্টের অ্যাসিঙ্ক্রোনাস প্রকৃতি এটিকে আশ্চর্যজনকভাবে জটিল করে তোলে। প্রতিশ্রুতি এবং অ্যাসিঙ্ক্রোনাস ফাংশনগুলির মাধ্যমে ব্যতিক্রমগুলি উড়ে গেলে কখন এবং কোথায় বিরতি দিতে হবে তা Chrome DevTools কীভাবে জানতে পারে?
এই পোস্টটি ক্যাচ ভবিষ্যদ্বাণীর চ্যালেঞ্জগুলির মধ্যে ডুব দেয় - আপনার কোডে পরবর্তীতে কোনও ব্যতিক্রম ধরা পড়বে কিনা তা অনুমান করার DevTools-এর ক্ষমতা৷ আমরা অন্বেষণ করব কেন এটি এত কঠিন এবং কীভাবে V8 (Chrome-কে চালিত জাভাস্ক্রিপ্ট ইঞ্জিন) সাম্প্রতিক উন্নতিগুলি এটিকে আরও নির্ভুল করে তুলছে, একটি মসৃণ ডিবাগিং অভিজ্ঞতার দিকে নিয়ে যাচ্ছে৷
কেন ভবিষ্যদ্বাণী বিষয় ধরা
Chrome DevTools-এ, আপনার কাছে শুধুমাত্র ধরা না পড়া ব্যতিক্রমগুলির জন্য কোড এক্সিকিউশন পজ করার একটি বিকল্প আছে, যেগুলি ধরা হয়েছে সেগুলিকে এড়িয়ে গিয়ে৷
দৃশ্যের আড়ালে, প্রসঙ্গ সংরক্ষণ করার জন্য একটি ব্যতিক্রম ঘটলে ডিবাগার অবিলম্বে বন্ধ হয়ে যায়। এটি একটি ভবিষ্যদ্বাণী কারণ, এই মুহুর্তে, কোডে বিশেষ করে অ্যাসিঙ্ক্রোনাস পরিস্থিতিতে ব্যতিক্রম ধরা পড়বে কি না তা নিশ্চিতভাবে জানা অসম্ভব। এই অনিশ্চয়তা প্রোগ্রাম আচরণের ভবিষ্যদ্বাণী করার সহজাত অসুবিধা থেকে উদ্ভূত হয়, যা হল্টিং সমস্যার মতো।
নিম্নলিখিত উদাহরণ বিবেচনা করুন: ডিবাগার কোথায় বিরতি করা উচিত? (পরবর্তী বিভাগে একটি উত্তর খুঁজুন।)
async function inner() {
throw new Error(); // Should the debugger pause here?
}
async function outer() {
try {
const promise = inner();
// ...
await promise;
} catch (e) {
// ... or should the debugger pause here?
}
}
ডিবাগারে ব্যতিক্রমগুলিতে বিরতি বিঘ্নিত হতে পারে এবং ঘন ঘন বাধা সৃষ্টি করতে পারে এবং অপরিচিত কোডে যেতে পারে। এটি প্রশমিত করার জন্য, আপনি শুধুমাত্র ধরা না পড়া ব্যতিক্রমগুলি ডিবাগ করতে বেছে নিতে পারেন, যা প্রকৃত বাগগুলিকে সংকেত দেওয়ার সম্ভাবনা বেশি৷ যাইহোক, এটি ক্যাচ ভবিষ্যদ্বাণীর নির্ভুলতার উপর নির্ভর করে।
ভুল ভবিষ্যদ্বাণী হতাশার দিকে পরিচালিত করে:
- মিথ্যা নেতিবাচক ("অপরাধিত" ভবিষ্যদ্বাণী করা যখন এটি ধরা হবে)। ডিবাগারে অপ্রয়োজনীয় স্টপ।
- মিথ্যা ইতিবাচক ( "ধরা" ভবিষ্যদ্বাণী করা যখন এটি ধরা পড়বে না) । গুরুতর ত্রুটিগুলি ধরার সুযোগ মিস করা হয়েছে, সম্ভাব্যভাবে আপনাকে প্রত্যাশিতগুলি সহ সমস্ত ব্যতিক্রম ডিবাগ করতে বাধ্য করে৷
ডিবাগিং বাধা কমানোর আরেকটি পদ্ধতি হল উপেক্ষা তালিকা ব্যবহার করে, যা নির্দিষ্ট তৃতীয় পক্ষের কোডের মধ্যে ব্যতিক্রমগুলিতে বিরতি প্রতিরোধ করে। যাইহোক, সঠিক ক্যাচ ভবিষ্যদ্বাণী এখনও এখানে গুরুত্বপূর্ণ। যদি তৃতীয় পক্ষের কোড থেকে উদ্ভূত একটি ব্যতিক্রম পালিয়ে যায় এবং আপনার নিজের কোডকে প্রভাবিত করে, আপনি এটি ডিবাগ করতে সক্ষম হতে চাইবেন।
কিভাবে অ্যাসিঙ্ক্রোনাস কোড কাজ করে
প্রতিশ্রুতি, async
এবং await
এবং অন্যান্য অ্যাসিঙ্ক্রোনাস প্যাটার্নগুলি এমন পরিস্থিতির দিকে নিয়ে যেতে পারে যেখানে একটি ব্যতিক্রম বা প্রত্যাখ্যান, পরিচালনা করার আগে, একটি কার্যকরী পথ নিতে পারে যা একটি ব্যতিক্রম নিক্ষেপ করার সময় নির্ধারণ করা কঠিন। এর কারণ হল প্রতিশ্রুতি অপেক্ষা করা নাও হতে পারে বা এর আগে ব্যতিক্রম না হওয়া পর্যন্ত ক্যাচ হ্যান্ডলার যোগ করা হতে পারে। আসুন আমাদের আগের উদাহরণটি দেখি:
async function inner() {
throw new Error();
}
async function outer() {
try {
const promise = inner();
// ...
await promise;
} catch (e) {
// ...
}
}
এই উদাহরণে, outer()
প্রথমে inner()
কল করে যা অবিলম্বে একটি ব্যতিক্রম নিক্ষেপ করে। এটি থেকে ডিবাগার উপসংহারে আসতে পারে যে inner()
একটি প্রত্যাখ্যান প্রতিশ্রুতি ফিরিয়ে দেবে তবে বর্তমানে কিছুই অপেক্ষা করছে না বা অন্যথায় সেই প্রতিশ্রুতি পরিচালনা করছে। ডিবাগার অনুমান করতে পারে যে outer()
সম্ভবত এটির জন্য অপেক্ষা করবে এবং অনুমান করবে যে এটি তার বর্তমান try
ব্লকে এটি করবে এবং তাই এটি পরিচালনা করবে কিন্তু ডিবাগার প্রত্যাখ্যান প্রতিশ্রুতি ফিরে না আসা পর্যন্ত এবং await
বিবৃতিটি শেষ পর্যন্ত পৌঁছানো না হওয়া পর্যন্ত এটি সম্পর্কে নিশ্চিত হতে পারে না।
ডিবাগার এমন কোনো গ্যারান্টি দিতে পারে না যে ক্যাচ ভবিষ্যদ্বাণী সঠিক হবে কিন্তু এটি সঠিকভাবে ভবিষ্যদ্বাণী করার জন্য সাধারণ কোডিং প্যাটার্নের জন্য বিভিন্ন হিউরিস্টিক ব্যবহার করে। এই নিদর্শনগুলি বোঝার জন্য, প্রতিশ্রুতিগুলি কীভাবে কাজ করে তা শিখতে সহায়তা করে।
V8-এ, একটি জাভাস্ক্রিপ্ট Promise
একটি বস্তু হিসাবে উপস্থাপন করা হয় যা তিনটি অবস্থার একটিতে হতে পারে: পূরণ, প্রত্যাখ্যান বা মুলতুবি। যদি একটি প্রতিশ্রুতি পূর্ণ অবস্থায় থাকে এবং আপনি .then()
পদ্ধতিতে কল করেন, একটি নতুন মুলতুবি প্রতিশ্রুতি তৈরি করা হয় এবং একটি নতুন প্রতিশ্রুতি প্রতিক্রিয়া কাজ নির্ধারিত হয় যা হ্যান্ডলারকে চালাবে এবং তারপর হ্যান্ডলারের ফলাফলের সাথে প্রতিশ্রুতিটি পূরণে সেট করে বা হ্যান্ডলার একটি ব্যতিক্রম নিক্ষেপ করলে প্রত্যাখ্যানে সেট করে। আপনি যদি প্রত্যাখ্যান করা প্রতিশ্রুতিতে .catch()
পদ্ধতিতে কল করেন তবে একই ঘটনা ঘটে। বিপরীতে, একটি প্রত্যাখ্যাত প্রতিশ্রুতিতে .then()
বা পূর্ণ প্রতিশ্রুতিতে .catch()
কল করা একই অবস্থায় একটি প্রতিশ্রুতি ফিরিয়ে দেবে এবং হ্যান্ডলার চালাবে না।
একটি মুলতুবি প্রতিশ্রুতিতে একটি প্রতিক্রিয়া তালিকা রয়েছে যেখানে প্রতিটি প্রতিক্রিয়া বস্তুতে একটি পূরণ হ্যান্ডলার বা প্রত্যাখ্যান হ্যান্ডলার (বা উভয়) এবং একটি প্রতিক্রিয়া প্রতিশ্রুতি রয়েছে। সুতরাং একটি মুলতুবি প্রতিশ্রুতিতে .then()
কল করলে একটি পূর্ণ হ্যান্ডলারের সাথে একটি প্রতিক্রিয়া যোগ হবে এবং সেই সাথে প্রতিক্রিয়া প্রতিশ্রুতির জন্য একটি নতুন মুলতুবি প্রতিশ্রুতি যুক্ত হবে, যা .then()
ফিরে আসবে। .catch()
কল করলে অনুরূপ প্রতিক্রিয়া যোগ হবে কিন্তু একটি প্রত্যাখ্যান হ্যান্ডলারের সাথে। দুটি আর্গুমেন্ট সহ .then()
কল করা উভয় হ্যান্ডলারের সাথে একটি প্রতিক্রিয়া তৈরি করে এবং .finally()
কল করা বা প্রতিশ্রুতির জন্য অপেক্ষা করা দুটি হ্যান্ডলারের সাথে একটি প্রতিক্রিয়া যোগ করবে যা এই বৈশিষ্ট্যগুলি বাস্তবায়নের জন্য নির্দিষ্ট বিল্ট-ইন ফাংশন।
যখন মুলতুবি প্রতিশ্রুতি শেষ পর্যন্ত পূর্ণ বা প্রত্যাখ্যান করা হয়, তখন প্রতিক্রিয়া কাজগুলি তার সমস্ত পূর্ণ হ্যান্ডলার বা প্রত্যাখ্যান করা সমস্ত হ্যান্ডলারের জন্য নির্ধারিত হবে। সংশ্লিষ্ট প্রতিক্রিয়া প্রতিশ্রুতি আপডেট করা হবে, সম্ভাব্য তাদের নিজস্ব প্রতিক্রিয়া কাজ ট্রিগার.
উদাহরণ
নিম্নলিখিত কোড বিবেচনা করুন:
return new Promise(() => {throw new Error();})
.then(() => console.log('Never happened'))
.catch(() => console.log('Caught'));
এটা স্পষ্ট নাও হতে পারে যে এই কোডে তিনটি স্বতন্ত্র Promise
বিষয় জড়িত। উপরের কোডটি নিম্নলিখিত কোডের সমতুল্য:
const promise1 = new Promise(() => {throw new Error();});
const promise2 = promise1.then(() => console.log('Never happened'));
const promise3 = promise2.catch(() => console.log('Caught'));
return promise3;
এই উদাহরণে, নিম্নলিখিত পদক্ষেপগুলি ঘটবে:
-
Promise
নির্মাণকারী বলা হয়. - একটি নতুন মুলতুবি
Promise
তৈরি করা হয়েছে। - বেনামী ফাংশন চালানো হয়.
- একটি ব্যতিক্রম নিক্ষেপ করা হয়. এই মুহুর্তে, ডিবাগারকে থামাতে হবে কিনা তা সিদ্ধান্ত নিতে হবে।
- প্রতিশ্রুতি কনস্ট্রাক্টর এই ব্যতিক্রমটি ক্যাচ করে এবং তারপরে তার প্রতিশ্রুতির অবস্থাকে
rejected
করে তার মান থ্রো করা ত্রুটিতে সেট করে। এটি এই প্রতিশ্রুতি ফিরিয়ে দেয়, যাpromise1
এ সংরক্ষিত হয়। -
.then()
কোনো প্রতিক্রিয়া কাজের সময়সূচী নির্ধারণ করে না কারণpromise1
rejected
অবস্থায় রয়েছে। পরিবর্তে, একটি নতুন প্রতিশ্রুতি (promise2
) ফেরত দেওয়া হয়েছে, যা একই ত্রুটির সাথে প্রত্যাখ্যাত অবস্থায় রয়েছে। -
.catch()
প্রদত্ত হ্যান্ডলারের সাথে একটি প্রতিক্রিয়া কাজের সময়সূচী করে এবং একটি নতুন মুলতুবি প্রতিক্রিয়া প্রতিশ্রুতি দেয়, যাpromise3
হিসাবে ফেরত দেওয়া হয়। এই মুহুর্তে ডিবাগার জানে যে ত্রুটিটি পরিচালনা করা হবে। - যখন প্রতিক্রিয়া টাস্ক চলে, তখন হ্যান্ডলার স্বাভাবিকভাবে ফিরে আসে এবং
promise3
এর অবস্থাfulfilled
হয়।
পরবর্তী উদাহরণের একটি অনুরূপ কাঠামো আছে কিন্তু মৃত্যুদন্ড সম্পূর্ণ ভিন্ন:
return Promise.resolve()
.then(() => {throw new Error();})
.then(() => console.log('Never happened'))
.catch(() => console.log('Caught'));
এটি এর সমতুল্য:
const promise1 = Promise.resolve();
const promise2 = promise1.then(() => {throw new Error();});
const promise3 = promise2.then(() => console.log('Never happened'));
const promise4 = promise3.catch(() => console.log('Caught'));
return promise4;
এই উদাহরণে, নিম্নলিখিত পদক্ষেপগুলি ঘটবে:
- একটি
Promise
fulfilled
অবস্থায় তৈরি করা হয় এবংpromise1
এ সংরক্ষণ করা হয়। - একটি প্রতিশ্রুতি প্রতিক্রিয়া টাস্ক প্রথম বেনামী ফাংশনের সাথে নির্ধারিত হয় এবং এর
(pending)
প্রতিক্রিয়া প্রতিশ্রুতিpromise2
হিসাবে ফেরত দেওয়া হয়। - একটি পরিপূর্ণ হ্যান্ডলার এবং তার প্রতিক্রিয়া প্রতিশ্রুতির সাথে
promise2
এ একটি প্রতিক্রিয়া যোগ করা হয়, যাpromise3
হিসাবে ফেরত দেওয়া হয়। - প্রত্যাখ্যাত হ্যান্ডলারের সাথে
promise3
এ একটি প্রতিক্রিয়া যোগ করা হয় এবং আরেকটি প্রতিক্রিয়া প্রতিশ্রুতি, যাpromise4
হিসাবে ফেরত দেওয়া হয়। - পদক্ষেপ 2 এ নির্ধারিত প্রতিক্রিয়া টাস্ক চালানো হয়।
- হ্যান্ডলার একটি ব্যতিক্রম নিক্ষেপ. এই মুহুর্তে ডিবাগারকে থামাতে হবে কিনা তা সিদ্ধান্ত নিতে হবে। বর্তমানে হ্যান্ডলার হল আপনার একমাত্র চলমান জাভাস্ক্রিপ্ট কোড।
- কারণ টাস্কটি একটি ব্যতিক্রমের সাথে শেষ হয়, যুক্ত প্রতিক্রিয়া প্রতিশ্রুতি (
promise2
) প্রত্যাখ্যান অবস্থায় সেট করা হয় এবং এর মানটি ছুঁড়ে দেওয়া ত্রুটিতে সেট করা হয়। - যেহেতু
promise2
একটি প্রতিক্রিয়া ছিল, এবং সেই প্রতিক্রিয়াটির কোনো প্রত্যাখ্যানকারী হ্যান্ডলার ছিল না, এর প্রতিক্রিয়া প্রতিশ্রুতি (promise3
) একই ত্রুটির সাথেrejected
জন্য সেট করা হয়েছে। - যেহেতু
promise3
একটি প্রতিক্রিয়া ছিল, এবং সেই প্রতিক্রিয়াটির একটি প্রত্যাখ্যান হ্যান্ডলার ছিল, একটি প্রতিশ্রুতি প্রতিক্রিয়া কাজ সেই হ্যান্ডলার এবং তার প্রতিক্রিয়া প্রতিশ্রুতির সাথে নির্ধারিত হয় (promise4
)। - যখন সেই প্রতিক্রিয়া টাস্কটি চলে, হ্যান্ডলারটি স্বাভাবিকভাবে ফিরে আসে এবং
promise4
এর অবস্থা পরিপূর্ণ হিসাবে পরিবর্তিত হয়।
ধরা ভবিষ্যদ্বাণী জন্য পদ্ধতি
ক্যাচ ভবিষ্যদ্বাণীর জন্য তথ্যের দুটি সম্ভাব্য উত্স রয়েছে। একটি হল কল স্ট্যাক। এটি সিঙ্ক্রোনাস ব্যতিক্রমগুলির জন্য সাউন্ড: ডিবাগার একইভাবে কল স্ট্যাকটি হাঁটতে পারে যেভাবে ব্যতিক্রম আনওয়াইন্ডিং কোড করবে এবং থামবে যদি এটি একটি ফ্রেম খুঁজে পায় যেখানে এটি try...catch
ব্লক। প্রত্যাখ্যান করা প্রতিশ্রুতি বা প্রতিশ্রুতি কন্সট্রাকটর বা অ্যাসিঙ্ক্রোনাস ফাংশনগুলিতে ব্যতিক্রমগুলির জন্য যা কখনও স্থগিত করা হয়নি, ডিবাগারও কল স্ট্যাকের উপর নির্ভর করে তবে, এই ক্ষেত্রে, এর পূর্বাভাস সব ক্ষেত্রে নির্ভরযোগ্য হতে পারে না। এর কারণ হল নিকটতম হ্যান্ডলারের কাছে একটি ব্যতিক্রম নিক্ষেপ করার পরিবর্তে, অ্যাসিঙ্ক্রোনাস কোড একটি প্রত্যাখ্যান করা ব্যতিক্রম ফিরিয়ে দেবে এবং ডিবাগারকে অবশ্যই কিছু অনুমান করতে হবে যে কলকারী এটির সাথে কী করবে।
প্রথমত, ডিবাগার অনুমান করে যে একটি ফাংশন যা একটি প্রত্যাবর্তিত প্রতিশ্রুতি প্রাপ্ত করে সেই প্রতিশ্রুতি বা একটি প্রাপ্ত প্রতিশ্রুতি ফেরত দিতে পারে যাতে স্ট্যাকের আরও উপরে অ্যাসিঙ্ক্রোনাস ফাংশনগুলি এটির জন্য অপেক্ষা করার সুযোগ পাবে। দ্বিতীয়ত, ডিবাগার অনুমান করে যে যদি একটি প্রতিশ্রুতি একটি অ্যাসিঙ্ক্রোনাস ফাংশনে ফিরিয়ে দেওয়া হয়, তবে এটি শীঘ্রই এটির জন্য অপেক্ষা করবে প্রথমে প্রবেশ না করে বা try...catch
ব্লক। এই অনুমানগুলির কোনটিই সঠিক হওয়ার গ্যারান্টিযুক্ত নয় তবে এগুলি অ্যাসিঙ্ক্রোনাস ফাংশন সহ সবচেয়ে সাধারণ কোডিং প্যাটার্নগুলির জন্য সঠিক ভবিষ্যদ্বাণী করার জন্য যথেষ্ট। ক্রোম সংস্করণ 125-এ, আমরা আরেকটি হিউরিস্টিক যোগ করেছি: ডিবাগার চেক করে যে একটি কলকারী .catch()
কল করতে চলেছে কিনা তা দুটি আর্গুমেন্ট সহ (বা .then()
ফেরত দেওয়া হবে, অথবা .then()
বা .finally()
এর পরে একটি .catch()
বা একটি দ্বি-আর্গুমেন্ট .then()
)। এই ক্ষেত্রে, ডিবাগার অনুমান করে যে আমরা যে প্রতিশ্রুতির সন্ধান করছি বা এটির সাথে সম্পর্কিত এইগুলি হল সেই পদ্ধতিগুলি, তাই প্রত্যাখ্যানটি ধরা পড়বে৷
তথ্যের দ্বিতীয় উৎস হল প্রতিশ্রুতি প্রতিক্রিয়া গাছ। ডিবাগার একটি মূল প্রতিশ্রুতি দিয়ে শুরু হয়। কখনও কখনও এটি একটি প্রতিশ্রুতি যার জন্য এটির reject()
পদ্ধতিটি বলা হয়েছে। আরও সাধারণভাবে, যখন প্রতিশ্রুতি প্রতিক্রিয়া কাজের সময় একটি ব্যতিক্রম বা প্রত্যাখ্যান ঘটে, এবং কল স্ট্যাকের কোন কিছুই এটি ধরার জন্য প্রদর্শিত হয় না, তখন ডিবাগার প্রতিক্রিয়াটির সাথে যুক্ত প্রতিশ্রুতি থেকে ট্রেস করে। ডিবাগার মুলতুবি প্রতিশ্রুতির সমস্ত প্রতিক্রিয়া দেখে এবং তাদের প্রত্যাখ্যান হ্যান্ডলার আছে কিনা তা দেখে। কোন প্রতিক্রিয়া না হলে, এটি প্রতিক্রিয়া প্রতিশ্রুতি দেখে এবং এটি থেকে পুনরাবৃত্তিমূলকভাবে ট্রেস করে। যদি সমস্ত প্রতিক্রিয়া শেষ পর্যন্ত একটি প্রত্যাখ্যান হ্যান্ডলারের দিকে নিয়ে যায়, ডিবাগার প্রতিশ্রুতি প্রত্যাখ্যানকে ধরা বলে মনে করে। কভার করার জন্য কিছু বিশেষ ক্ষেত্রে আছে, উদাহরণস্বরূপ, একটি .finally()
কলের জন্য অন্তর্নির্মিত প্রত্যাখ্যান হ্যান্ডলারকে গণনা না করা।
প্রতিশ্রুতি প্রতিক্রিয়া গাছ তথ্যের একটি নির্ভরযোগ্য উৎস প্রদান করে যদি তথ্য থাকে। কিছু ক্ষেত্রে, যেমন Promise.reject()
কে কল করা বা Promise
কনস্ট্রাক্টরে বা একটি অ্যাসিঙ্ক ফাংশনে যা এখনও কিছুর জন্য অপেক্ষা করেনি, ট্রেস করার জন্য কোন প্রতিক্রিয়া হবে না এবং ডিবাগারকে একা কল স্ট্যাকের উপর নির্ভর করতে হবে। অন্যান্য ক্ষেত্রে, প্রতিশ্রুতি প্রতিক্রিয়া গাছে সাধারণত ক্যাচের পূর্বাভাস অনুমান করার জন্য প্রয়োজনীয় হ্যান্ডলার থাকে তবে এটি সর্বদা সম্ভব যে পরে আরও হ্যান্ডলার যোগ করা হবে যা ধরা থেকে ধরা না হওয়া বা বিপরীতে ব্যতিক্রম পরিবর্তন করবে। এছাড়াও Promise.all/any/race
দ্বারা তৈরি করা প্রতিশ্রুতি রয়েছে, যেখানে গ্রুপের অন্যান্য প্রতিশ্রুতিগুলি কীভাবে প্রত্যাখ্যান করা হয় তা প্রভাবিত করতে পারে। এই পদ্ধতিগুলির জন্য, ডিবাগার অনুমান করে একটি প্রতিশ্রুতি প্রত্যাখ্যান ফরোয়ার্ড করা হবে যদি প্রতিশ্রুতি এখনও মুলতুবি থাকে।
নিম্নলিখিত দুটি উদাহরণ দেখুন:
যদিও ধরা ব্যতিক্রমগুলির এই দুটি উদাহরণ একই রকম দেখায়, তাদের জন্য বেশ ভিন্ন ক্যাচ ভবিষ্যদ্বাণী হিউরিস্টিকস প্রয়োজন। প্রথম উদাহরণে, একটি সমাধান করা প্রতিশ্রুতি তৈরি করা হয়, তারপর .then()
এর জন্য একটি প্রতিক্রিয়া কাজ নির্ধারিত হয় যা একটি ব্যতিক্রম ছুঁড়ে দেয়, তারপর .catch()
প্রতিক্রিয়া প্রতিশ্রুতিতে একটি প্রত্যাখ্যান হ্যান্ডলার সংযুক্ত করতে বলা হয়। প্রতিক্রিয়া টাস্ক চালানো হলে, ব্যতিক্রমটি নিক্ষেপ করা হবে, এবং প্রতিশ্রুতি প্রতিক্রিয়া ট্রিতে ক্যাচ হ্যান্ডলার থাকবে, তাই এটি ধরা হিসাবে সনাক্ত করা হবে। দ্বিতীয় উদাহরণে, একটি ক্যাচ হ্যান্ডলার যোগ করার কোড চালানোর আগে প্রতিশ্রুতি অবিলম্বে প্রত্যাখ্যান করা হয়, তাই প্রতিশ্রুতির প্রতিক্রিয়া ট্রিতে কোনো প্রত্যাখ্যান হ্যান্ডলার নেই। ডিবাগারকে অবশ্যই কল স্ট্যাকের দিকে তাকাতে হবে কিন্তু কোন try...catch
ব্লকও। এটি সঠিকভাবে ভবিষ্যদ্বাণী করার জন্য, ডিবাগার .catch()
এ কলটি খুঁজে পেতে কোডে বর্তমান অবস্থানের আগে স্ক্যান করে, এবং সেই ভিত্তিতে অনুমান করে যে প্রত্যাখ্যানটি শেষ পর্যন্ত পরিচালনা করা হবে।
সারাংশ
আশা করি, এই ব্যাখ্যাটি কীভাবে Chrome DevTools-এ ক্যাচ ভবিষ্যদ্বাণী কাজ করে, এর শক্তি এবং সীমাবদ্ধতার উপর আলোকপাত করেছে। আপনি যদি ভুল পূর্বাভাসের কারণে ডিবাগিং সমস্যার সম্মুখীন হন, তাহলে এই বিকল্পগুলি বিবেচনা করুন:
- ভবিষ্যদ্বাণী করার জন্য কোডিং প্যাটার্নটিকে আরও সহজ কিছুতে পরিবর্তন করুন, যেমন অ্যাসিঙ্ক ফাংশন ব্যবহার করা।
- DevTools যখন বন্ধ করতে ব্যর্থ হয় তখন সব ব্যতিক্রমের উপর বিরতি বেছে নিন।
- একটি "এখানে কখনও বিরতি দেবেন না" ব্রেকপয়েন্ট বা শর্তসাপেক্ষ ব্রেকপয়েন্ট ব্যবহার করুন যদি ডিবাগারটি এমন কোথাও থামে যা আপনি এটি করতে চান না।
স্বীকৃতি
আমাদের গভীর কৃতজ্ঞতা সোফিয়া ইমেলিয়ানোভা এবং জেসেলিন ইয়েনের কাছে তাদের অমূল্য সাহায্যের জন্য এই পোস্টটি সম্পাদনা করার জন্য!
,ওয়েব অ্যাপ্লিকেশানগুলিতে ডিবাগিং ব্যতিক্রমগুলি সহজ বলে মনে হয়: কিছু ভুল হয়ে গেলে এক্সিকিউশন থামান এবং তদন্ত করুন। কিন্তু জাভাস্ক্রিপ্টের অ্যাসিঙ্ক্রোনাস প্রকৃতি এটিকে আশ্চর্যজনকভাবে জটিল করে তোলে। প্রতিশ্রুতি এবং অ্যাসিঙ্ক্রোনাস ফাংশনগুলির মাধ্যমে ব্যতিক্রমগুলি উড়ে গেলে কখন এবং কোথায় বিরতি দিতে হবে তা Chrome DevTools কীভাবে জানতে পারে?
এই পোস্টটি ক্যাচ ভবিষ্যদ্বাণীর চ্যালেঞ্জগুলির মধ্যে ডুব দেয় - আপনার কোডে পরবর্তীতে কোনও ব্যতিক্রম ধরা পড়বে কিনা তা অনুমান করার DevTools-এর ক্ষমতা৷ আমরা অন্বেষণ করব কেন এটি এত কঠিন এবং কীভাবে V8 (Chrome-কে চালিত জাভাস্ক্রিপ্ট ইঞ্জিন) সাম্প্রতিক উন্নতিগুলি এটিকে আরও নির্ভুল করে তুলছে, একটি মসৃণ ডিবাগিং অভিজ্ঞতার দিকে নিয়ে যাচ্ছে৷
কেন ভবিষ্যদ্বাণী বিষয় ধরা
Chrome DevTools-এ, আপনার কাছে শুধুমাত্র ধরা না পড়া ব্যতিক্রমগুলির জন্য কোড এক্সিকিউশন পজ করার একটি বিকল্প আছে, যেগুলি ধরা হয়েছে সেগুলিকে এড়িয়ে গিয়ে৷
দৃশ্যের আড়ালে, প্রসঙ্গ সংরক্ষণ করার জন্য একটি ব্যতিক্রম ঘটলে ডিবাগার অবিলম্বে বন্ধ হয়ে যায়। এটি একটি ভবিষ্যদ্বাণী কারণ, এই মুহুর্তে, কোডে বিশেষ করে অ্যাসিঙ্ক্রোনাস পরিস্থিতিতে ব্যতিক্রম ধরা পড়বে কি না তা নিশ্চিতভাবে জানা অসম্ভব। এই অনিশ্চয়তা প্রোগ্রাম আচরণের ভবিষ্যদ্বাণী করার সহজাত অসুবিধা থেকে উদ্ভূত হয়, যা হল্টিং সমস্যার মতো।
নিম্নলিখিত উদাহরণ বিবেচনা করুন: ডিবাগার কোথায় বিরতি করা উচিত? (পরবর্তী বিভাগে একটি উত্তর খুঁজুন।)
async function inner() {
throw new Error(); // Should the debugger pause here?
}
async function outer() {
try {
const promise = inner();
// ...
await promise;
} catch (e) {
// ... or should the debugger pause here?
}
}
ডিবাগারে ব্যতিক্রমগুলিতে বিরতি বিঘ্নিত হতে পারে এবং ঘন ঘন বাধা সৃষ্টি করতে পারে এবং অপরিচিত কোডে যেতে পারে। এটি প্রশমিত করার জন্য, আপনি শুধুমাত্র ধরা না পড়া ব্যতিক্রমগুলি ডিবাগ করতে বেছে নিতে পারেন, যা প্রকৃত বাগগুলিকে সংকেত দেওয়ার সম্ভাবনা বেশি৷ যাইহোক, এটি ক্যাচ ভবিষ্যদ্বাণীর নির্ভুলতার উপর নির্ভর করে।
ভুল ভবিষ্যদ্বাণী হতাশার দিকে পরিচালিত করে:
- মিথ্যা নেতিবাচক ("অপরাধিত" ভবিষ্যদ্বাণী করা যখন এটি ধরা হবে)। ডিবাগারে অপ্রয়োজনীয় স্টপ।
- মিথ্যা ইতিবাচক ( "ধরা" ভবিষ্যদ্বাণী করা যখন এটি ধরা পড়বে না) । গুরুতর ত্রুটিগুলি ধরার সুযোগ মিস করা হয়েছে, সম্ভাব্যভাবে আপনাকে প্রত্যাশিতগুলি সহ সমস্ত ব্যতিক্রম ডিবাগ করতে বাধ্য করে৷
ডিবাগিং বাধা কমানোর আরেকটি পদ্ধতি হল উপেক্ষা তালিকা ব্যবহার করে, যা নির্দিষ্ট তৃতীয় পক্ষের কোডের মধ্যে ব্যতিক্রমগুলিতে বিরতি প্রতিরোধ করে। যাইহোক, সঠিক ক্যাচ ভবিষ্যদ্বাণী এখনও এখানে গুরুত্বপূর্ণ। যদি তৃতীয় পক্ষের কোড থেকে উদ্ভূত একটি ব্যতিক্রম পালিয়ে যায় এবং আপনার নিজের কোডকে প্রভাবিত করে, আপনি এটি ডিবাগ করতে সক্ষম হতে চাইবেন।
কিভাবে অ্যাসিঙ্ক্রোনাস কোড কাজ করে
প্রতিশ্রুতি, async
এবং await
এবং অন্যান্য অ্যাসিঙ্ক্রোনাস প্যাটার্নগুলি এমন পরিস্থিতির দিকে নিয়ে যেতে পারে যেখানে একটি ব্যতিক্রম বা প্রত্যাখ্যান, পরিচালনা করার আগে, একটি কার্যকরী পথ নিতে পারে যা একটি ব্যতিক্রম নিক্ষেপ করার সময় নির্ধারণ করা কঠিন। এর কারণ হল প্রতিশ্রুতি অপেক্ষা করা নাও হতে পারে বা এর আগে ব্যতিক্রম না হওয়া পর্যন্ত ক্যাচ হ্যান্ডলার যোগ করা হতে পারে। আসুন আমাদের আগের উদাহরণটি দেখি:
async function inner() {
throw new Error();
}
async function outer() {
try {
const promise = inner();
// ...
await promise;
} catch (e) {
// ...
}
}
এই উদাহরণে, outer()
প্রথমে inner()
কল করে যা অবিলম্বে একটি ব্যতিক্রম নিক্ষেপ করে। এটি থেকে ডিবাগার উপসংহারে আসতে পারে যে inner()
একটি প্রত্যাখ্যান প্রতিশ্রুতি ফিরিয়ে দেবে তবে বর্তমানে কিছুই অপেক্ষা করছে না বা অন্যথায় সেই প্রতিশ্রুতি পরিচালনা করছে। ডিবাগার অনুমান করতে পারে যে outer()
সম্ভবত এটির জন্য অপেক্ষা করবে এবং অনুমান করবে যে এটি তার বর্তমান try
ব্লকে এটি করবে এবং তাই এটি পরিচালনা করবে কিন্তু ডিবাগার প্রত্যাখ্যান প্রতিশ্রুতি ফিরে না আসা পর্যন্ত এবং await
বিবৃতিটি শেষ পর্যন্ত পৌঁছানো না হওয়া পর্যন্ত এটি সম্পর্কে নিশ্চিত হতে পারে না।
ডিবাগার এমন কোনো গ্যারান্টি দিতে পারে না যে ক্যাচ ভবিষ্যদ্বাণী সঠিক হবে কিন্তু এটি সঠিকভাবে ভবিষ্যদ্বাণী করার জন্য সাধারণ কোডিং প্যাটার্নের জন্য বিভিন্ন হিউরিস্টিক ব্যবহার করে। এই নিদর্শনগুলি বোঝার জন্য, প্রতিশ্রুতিগুলি কীভাবে কাজ করে তা শিখতে সহায়তা করে।
V8-এ, একটি জাভাস্ক্রিপ্ট Promise
একটি বস্তু হিসাবে উপস্থাপন করা হয় যা তিনটি অবস্থার একটিতে হতে পারে: পূরণ, প্রত্যাখ্যান বা মুলতুবি। যদি একটি প্রতিশ্রুতি পূর্ণ অবস্থায় থাকে এবং আপনি .then()
পদ্ধতিতে কল করেন, একটি নতুন মুলতুবি প্রতিশ্রুতি তৈরি করা হয় এবং একটি নতুন প্রতিশ্রুতি প্রতিক্রিয়া কাজ নির্ধারিত হয় যা হ্যান্ডলারকে চালাবে এবং তারপর হ্যান্ডলারের ফলাফলের সাথে প্রতিশ্রুতিটি পূরণে সেট করে বা হ্যান্ডলার একটি ব্যতিক্রম নিক্ষেপ করলে প্রত্যাখ্যানে সেট করে। আপনি যদি প্রত্যাখ্যান করা প্রতিশ্রুতিতে .catch()
পদ্ধতিতে কল করেন তবে একই ঘটনা ঘটে। বিপরীতে, একটি প্রত্যাখ্যাত প্রতিশ্রুতিতে .then()
বা পূর্ণ প্রতিশ্রুতিতে .catch()
কল করা একই অবস্থায় একটি প্রতিশ্রুতি ফিরিয়ে দেবে এবং হ্যান্ডলার চালাবে না।
একটি মুলতুবি প্রতিশ্রুতিতে একটি প্রতিক্রিয়া তালিকা রয়েছে যেখানে প্রতিটি প্রতিক্রিয়া বস্তুতে একটি পূরণ হ্যান্ডলার বা প্রত্যাখ্যান হ্যান্ডলার (বা উভয়) এবং একটি প্রতিক্রিয়া প্রতিশ্রুতি রয়েছে। সুতরাং একটি মুলতুবি প্রতিশ্রুতিতে .then()
কল করলে একটি পূর্ণ হ্যান্ডলারের সাথে একটি প্রতিক্রিয়া যোগ হবে এবং সেই সাথে প্রতিক্রিয়া প্রতিশ্রুতির জন্য একটি নতুন মুলতুবি প্রতিশ্রুতি যুক্ত হবে, যা .then()
ফিরে আসবে। .catch()
কল করলে অনুরূপ প্রতিক্রিয়া যোগ হবে কিন্তু একটি প্রত্যাখ্যান হ্যান্ডলারের সাথে। দুটি আর্গুমেন্ট সহ .then()
কল করা উভয় হ্যান্ডলারের সাথে একটি প্রতিক্রিয়া তৈরি করে এবং .finally()
কল করা বা প্রতিশ্রুতির জন্য অপেক্ষা করা দুটি হ্যান্ডলারের সাথে একটি প্রতিক্রিয়া যোগ করবে যা এই বৈশিষ্ট্যগুলি বাস্তবায়নের জন্য নির্দিষ্ট বিল্ট-ইন ফাংশন।
যখন মুলতুবি প্রতিশ্রুতি শেষ পর্যন্ত পূর্ণ বা প্রত্যাখ্যান করা হয়, তখন প্রতিক্রিয়া কাজগুলি তার সমস্ত পূর্ণ হ্যান্ডলার বা প্রত্যাখ্যান করা সমস্ত হ্যান্ডলারের জন্য নির্ধারিত হবে। সংশ্লিষ্ট প্রতিক্রিয়া প্রতিশ্রুতি আপডেট করা হবে, সম্ভাব্য তাদের নিজস্ব প্রতিক্রিয়া কাজ ট্রিগার.
উদাহরণ
নিম্নলিখিত কোড বিবেচনা করুন:
return new Promise(() => {throw new Error();})
.then(() => console.log('Never happened'))
.catch(() => console.log('Caught'));
এটা স্পষ্ট নাও হতে পারে যে এই কোডে তিনটি স্বতন্ত্র Promise
বিষয় জড়িত। উপরের কোডটি নিম্নলিখিত কোডের সমতুল্য:
const promise1 = new Promise(() => {throw new Error();});
const promise2 = promise1.then(() => console.log('Never happened'));
const promise3 = promise2.catch(() => console.log('Caught'));
return promise3;
এই উদাহরণে, নিম্নলিখিত পদক্ষেপগুলি ঘটবে:
-
Promise
নির্মাণকারী বলা হয়. - একটি নতুন মুলতুবি
Promise
তৈরি করা হয়েছে। - বেনামী ফাংশন চালানো হয়.
- একটি ব্যতিক্রম নিক্ষেপ করা হয়. এই মুহুর্তে, ডিবাগারকে থামাতে হবে কিনা তা সিদ্ধান্ত নিতে হবে।
- প্রতিশ্রুতি কনস্ট্রাক্টর এই ব্যতিক্রমটি ক্যাচ করে এবং তারপরে তার প্রতিশ্রুতির অবস্থাকে
rejected
করে তার মান থ্রো করা ত্রুটিতে সেট করে। এটি এই প্রতিশ্রুতি ফিরিয়ে দেয়, যাpromise1
এ সংরক্ষিত হয়। -
.then()
কোনো প্রতিক্রিয়া কাজের সময়সূচী নির্ধারণ করে না কারণpromise1
rejected
অবস্থায় রয়েছে। পরিবর্তে, একটি নতুন প্রতিশ্রুতি (promise2
) ফেরত দেওয়া হয়েছে, যা একই ত্রুটির সাথে প্রত্যাখ্যাত অবস্থায় রয়েছে। -
.catch()
প্রদত্ত হ্যান্ডলারের সাথে একটি প্রতিক্রিয়া কাজের সময়সূচী করে এবং একটি নতুন মুলতুবি প্রতিক্রিয়া প্রতিশ্রুতি দেয়, যাpromise3
হিসাবে ফেরত দেওয়া হয়। এই মুহুর্তে ডিবাগার জানে যে ত্রুটিটি পরিচালনা করা হবে। - যখন প্রতিক্রিয়া টাস্ক চলে, তখন হ্যান্ডলার স্বাভাবিকভাবে ফিরে আসে এবং
promise3
এর অবস্থাfulfilled
হয়।
পরবর্তী উদাহরণের একটি অনুরূপ কাঠামো আছে কিন্তু মৃত্যুদন্ড সম্পূর্ণ ভিন্ন:
return Promise.resolve()
.then(() => {throw new Error();})
.then(() => console.log('Never happened'))
.catch(() => console.log('Caught'));
এটি এর সমতুল্য:
const promise1 = Promise.resolve();
const promise2 = promise1.then(() => {throw new Error();});
const promise3 = promise2.then(() => console.log('Never happened'));
const promise4 = promise3.catch(() => console.log('Caught'));
return promise4;
এই উদাহরণে, নিম্নলিখিত পদক্ষেপগুলি ঘটবে:
- একটি
Promise
fulfilled
অবস্থায় তৈরি করা হয় এবংpromise1
এ সংরক্ষণ করা হয়। - একটি প্রতিশ্রুতি প্রতিক্রিয়া টাস্ক প্রথম বেনামী ফাংশনের সাথে নির্ধারিত হয় এবং এর
(pending)
প্রতিক্রিয়া প্রতিশ্রুতিpromise2
হিসাবে ফেরত দেওয়া হয়। - একটি পরিপূর্ণ হ্যান্ডলার এবং তার প্রতিক্রিয়া প্রতিশ্রুতির সাথে
promise2
এ একটি প্রতিক্রিয়া যোগ করা হয়, যাpromise3
হিসাবে ফেরত দেওয়া হয়। - প্রত্যাখ্যাত হ্যান্ডলারের সাথে
promise3
এ একটি প্রতিক্রিয়া যোগ করা হয় এবং আরেকটি প্রতিক্রিয়া প্রতিশ্রুতি, যাpromise4
হিসাবে ফেরত দেওয়া হয়। - পদক্ষেপ 2 এ নির্ধারিত প্রতিক্রিয়া টাস্ক চালানো হয়।
- হ্যান্ডলার একটি ব্যতিক্রম নিক্ষেপ. এই মুহুর্তে ডিবাগারকে থামাতে হবে কিনা তা সিদ্ধান্ত নিতে হবে। বর্তমানে হ্যান্ডলার হল আপনার একমাত্র চলমান জাভাস্ক্রিপ্ট কোড।
- কারণ টাস্কটি একটি ব্যতিক্রমের সাথে শেষ হয়, যুক্ত প্রতিক্রিয়া প্রতিশ্রুতি (
promise2
) প্রত্যাখ্যান অবস্থায় সেট করা হয় এবং এর মানটি ছুঁড়ে দেওয়া ত্রুটিতে সেট করা হয়। - যেহেতু
promise2
একটি প্রতিক্রিয়া ছিল, এবং সেই প্রতিক্রিয়াটির কোনো প্রত্যাখ্যানকারী হ্যান্ডলার ছিল না, এর প্রতিক্রিয়া প্রতিশ্রুতি (promise3
) একই ত্রুটির সাথেrejected
জন্য সেট করা হয়েছে। - যেহেতু
promise3
একটি প্রতিক্রিয়া ছিল, এবং সেই প্রতিক্রিয়াটির একটি প্রত্যাখ্যান হ্যান্ডলার ছিল, একটি প্রতিশ্রুতি প্রতিক্রিয়া কাজ সেই হ্যান্ডলার এবং তার প্রতিক্রিয়া প্রতিশ্রুতির সাথে নির্ধারিত হয় (promise4
)। - যখন সেই প্রতিক্রিয়া টাস্কটি চলে, হ্যান্ডলারটি স্বাভাবিকভাবে ফিরে আসে এবং
promise4
এর অবস্থা পরিপূর্ণ হিসাবে পরিবর্তিত হয়।
ধরা ভবিষ্যদ্বাণী জন্য পদ্ধতি
ক্যাচ ভবিষ্যদ্বাণীর জন্য তথ্যের দুটি সম্ভাব্য উত্স রয়েছে। একটি হল কল স্ট্যাক। এটি সিঙ্ক্রোনাস ব্যতিক্রমগুলির জন্য সাউন্ড: ডিবাগার একইভাবে কল স্ট্যাকটি হাঁটতে পারে যেভাবে ব্যতিক্রম আনওয়াইন্ডিং কোড করবে এবং থামবে যদি এটি একটি ফ্রেম খুঁজে পায় যেখানে এটি try...catch
ব্লক। প্রত্যাখ্যান করা প্রতিশ্রুতি বা প্রতিশ্রুতি কন্সট্রাকটর বা অ্যাসিঙ্ক্রোনাস ফাংশনগুলিতে ব্যতিক্রমগুলির জন্য যা কখনও স্থগিত করা হয়নি, ডিবাগারও কল স্ট্যাকের উপর নির্ভর করে তবে, এই ক্ষেত্রে, এর পূর্বাভাস সব ক্ষেত্রে নির্ভরযোগ্য হতে পারে না। এর কারণ হল নিকটতম হ্যান্ডলারের কাছে একটি ব্যতিক্রম নিক্ষেপ করার পরিবর্তে, অ্যাসিঙ্ক্রোনাস কোড একটি প্রত্যাখ্যান করা ব্যতিক্রম ফিরিয়ে দেবে এবং ডিবাগারকে অবশ্যই কিছু অনুমান করতে হবে যে কলকারী এটির সাথে কী করবে।
প্রথমত, ডিবাগার অনুমান করে যে একটি ফাংশন যা একটি প্রত্যাবর্তিত প্রতিশ্রুতি প্রাপ্ত করে সেই প্রতিশ্রুতি বা একটি প্রাপ্ত প্রতিশ্রুতি ফেরত দিতে পারে যাতে স্ট্যাকের আরও উপরে অ্যাসিঙ্ক্রোনাস ফাংশনগুলি এটির জন্য অপেক্ষা করার সুযোগ পাবে। দ্বিতীয়ত, ডিবাগার অনুমান করে যে যদি একটি প্রতিশ্রুতি একটি অ্যাসিঙ্ক্রোনাস ফাংশনে ফিরিয়ে দেওয়া হয়, তবে এটি শীঘ্রই এটির জন্য অপেক্ষা করবে প্রথমে প্রবেশ না করে বা try...catch
ব্লক। এই অনুমানগুলির কোনটিই সঠিক হওয়ার গ্যারান্টিযুক্ত নয় তবে এগুলি অ্যাসিঙ্ক্রোনাস ফাংশন সহ সবচেয়ে সাধারণ কোডিং প্যাটার্নগুলির জন্য সঠিক ভবিষ্যদ্বাণী করার জন্য যথেষ্ট। ক্রোম সংস্করণ 125-এ, আমরা আরেকটি হিউরিস্টিক যোগ করেছি: ডিবাগার চেক করে যে একটি কলকারী .catch()
কল করতে চলেছে কিনা তা দুটি আর্গুমেন্ট সহ (বা .then()
ফেরত দেওয়া হবে, অথবা .then()
বা .finally()
এর পরে একটি .catch()
বা একটি দ্বি-আর্গুমেন্ট .then()
)। এই ক্ষেত্রে, ডিবাগার অনুমান করে যে আমরা যে প্রতিশ্রুতির সন্ধান করছি বা এটির সাথে সম্পর্কিত এইগুলি হল সেই পদ্ধতিগুলি, তাই প্রত্যাখ্যানটি ধরা পড়বে৷
তথ্যের দ্বিতীয় উৎস হল প্রতিশ্রুতি প্রতিক্রিয়া গাছ। ডিবাগার একটি মূল প্রতিশ্রুতি দিয়ে শুরু হয়। কখনও কখনও এটি একটি প্রতিশ্রুতি যার জন্য এটির reject()
পদ্ধতিটি বলা হয়েছে। আরও সাধারণভাবে, যখন প্রতিশ্রুতি প্রতিক্রিয়া কাজের সময় একটি ব্যতিক্রম বা প্রত্যাখ্যান ঘটে, এবং কল স্ট্যাকের কোন কিছুই এটি ধরার জন্য প্রদর্শিত হয় না, তখন ডিবাগার প্রতিক্রিয়াটির সাথে যুক্ত প্রতিশ্রুতি থেকে ট্রেস করে। ডিবাগার মুলতুবি প্রতিশ্রুতির সমস্ত প্রতিক্রিয়া দেখে এবং তাদের প্রত্যাখ্যান হ্যান্ডলার আছে কিনা তা দেখে। কোন প্রতিক্রিয়া না হলে, এটি প্রতিক্রিয়া প্রতিশ্রুতি দেখে এবং এটি থেকে পুনরাবৃত্তিমূলকভাবে ট্রেস করে। যদি সমস্ত প্রতিক্রিয়া শেষ পর্যন্ত একটি প্রত্যাখ্যান হ্যান্ডলারের দিকে নিয়ে যায়, ডিবাগার প্রতিশ্রুতি প্রত্যাখ্যানকে ধরা বলে মনে করে। কভার করার জন্য কিছু বিশেষ ক্ষেত্রে আছে, উদাহরণস্বরূপ, একটি .finally()
কলের জন্য অন্তর্নির্মিত প্রত্যাখ্যান হ্যান্ডলারকে গণনা না করা।
প্রতিশ্রুতি প্রতিক্রিয়া গাছ তথ্যের একটি নির্ভরযোগ্য উৎস প্রদান করে যদি তথ্য থাকে। কিছু ক্ষেত্রে, যেমন Promise.reject()
কে কল করা বা Promise
কনস্ট্রাক্টরে বা একটি অ্যাসিঙ্ক ফাংশনে যা এখনও কিছুর জন্য অপেক্ষা করেনি, ট্রেস করার জন্য কোন প্রতিক্রিয়া হবে না এবং ডিবাগারকে একা কল স্ট্যাকের উপর নির্ভর করতে হবে। অন্যান্য ক্ষেত্রে, প্রতিশ্রুতি প্রতিক্রিয়া গাছে সাধারণত ক্যাচের পূর্বাভাস অনুমান করার জন্য প্রয়োজনীয় হ্যান্ডলার থাকে তবে এটি সর্বদা সম্ভব যে পরে আরও হ্যান্ডলার যোগ করা হবে যা ধরা থেকে ধরা না হওয়া বা বিপরীতে ব্যতিক্রম পরিবর্তন করবে। এছাড়াও Promise.all/any/race
দ্বারা তৈরি করা প্রতিশ্রুতি রয়েছে, যেখানে গ্রুপের অন্যান্য প্রতিশ্রুতিগুলি কীভাবে প্রত্যাখ্যান করা হয় তা প্রভাবিত করতে পারে। এই পদ্ধতিগুলির জন্য, ডিবাগার অনুমান করে একটি প্রতিশ্রুতি প্রত্যাখ্যান ফরোয়ার্ড করা হবে যদি প্রতিশ্রুতি এখনও মুলতুবি থাকে।
নিম্নলিখিত দুটি উদাহরণ দেখুন:
যদিও ধরা ব্যতিক্রমগুলির এই দুটি উদাহরণ একই রকম দেখায়, তাদের জন্য বেশ ভিন্ন ক্যাচ ভবিষ্যদ্বাণী হিউরিস্টিকস প্রয়োজন। প্রথম উদাহরণে, একটি সমাধান করা প্রতিশ্রুতি তৈরি করা হয়, তারপর .then()
এর জন্য একটি প্রতিক্রিয়া কাজ নির্ধারিত হয় যা একটি ব্যতিক্রম ছুঁড়ে দেয়, তারপর .catch()
প্রতিক্রিয়া প্রতিশ্রুতিতে একটি প্রত্যাখ্যান হ্যান্ডলার সংযুক্ত করতে বলা হয়। প্রতিক্রিয়া টাস্ক চালানো হলে, ব্যতিক্রমটি নিক্ষেপ করা হবে, এবং প্রতিশ্রুতি প্রতিক্রিয়া ট্রিতে ক্যাচ হ্যান্ডলার থাকবে, তাই এটি ধরা হিসাবে সনাক্ত করা হবে। দ্বিতীয় উদাহরণে, একটি ক্যাচ হ্যান্ডলার যোগ করার কোড চালানোর আগে প্রতিশ্রুতি অবিলম্বে প্রত্যাখ্যান করা হয়, তাই প্রতিশ্রুতির প্রতিক্রিয়া ট্রিতে কোনো প্রত্যাখ্যান হ্যান্ডলার নেই। ডিবাগারকে অবশ্যই কল স্ট্যাকের দিকে তাকাতে হবে কিন্তু কোন try...catch
ব্লকও। এটি সঠিকভাবে ভবিষ্যদ্বাণী করার জন্য, ডিবাগার .catch()
এ কলটি খুঁজে পেতে কোডে বর্তমান অবস্থানের আগে স্ক্যান করে, এবং সেই ভিত্তিতে অনুমান করে যে প্রত্যাখ্যানটি শেষ পর্যন্ত পরিচালনা করা হবে।
সারাংশ
আশা করি, এই ব্যাখ্যাটি কীভাবে Chrome DevTools-এ ক্যাচ ভবিষ্যদ্বাণী কাজ করে, এর শক্তি এবং সীমাবদ্ধতার উপর আলোকপাত করেছে। আপনি যদি ভুল পূর্বাভাসের কারণে ডিবাগিং সমস্যার সম্মুখীন হন, তাহলে এই বিকল্পগুলি বিবেচনা করুন:
- ভবিষ্যদ্বাণী করার জন্য কোডিং প্যাটার্নটিকে আরও সহজ কিছুতে পরিবর্তন করুন, যেমন অ্যাসিঙ্ক ফাংশন ব্যবহার করা।
- DevTools যখন বন্ধ করতে ব্যর্থ হয় তখন সব ব্যতিক্রমের উপর বিরতি বেছে নিন।
- একটি "এখানে কখনও বিরতি দেবেন না" ব্রেকপয়েন্ট বা শর্তসাপেক্ষ ব্রেকপয়েন্ট ব্যবহার করুন যদি ডিবাগারটি এমন কোথাও থামে যা আপনি এটি করতে চান না।
স্বীকৃতি
আমাদের গভীর কৃতজ্ঞতা সোফিয়া ইমেলিয়ানোভা এবং জেসেলিন ইয়েনের কাছে তাদের অমূল্য সাহায্যের জন্য এই পোস্টটি সম্পাদনা করার জন্য!
,ওয়েব অ্যাপ্লিকেশানগুলিতে ডিবাগিং ব্যতিক্রমগুলি সহজ বলে মনে হয়: কিছু ভুল হয়ে গেলে এক্সিকিউশন থামান এবং তদন্ত করুন। কিন্তু জাভাস্ক্রিপ্টের অ্যাসিঙ্ক্রোনাস প্রকৃতি এটিকে আশ্চর্যজনকভাবে জটিল করে তোলে। প্রতিশ্রুতি এবং অ্যাসিঙ্ক্রোনাস ফাংশনগুলির মাধ্যমে ব্যতিক্রমগুলি উড়ে গেলে কখন এবং কোথায় বিরতি দিতে হবে তা Chrome DevTools কীভাবে জানতে পারে?
এই পোস্টটি ক্যাচ ভবিষ্যদ্বাণীর চ্যালেঞ্জগুলির মধ্যে ডুব দেয় - আপনার কোডে পরবর্তীতে কোনও ব্যতিক্রম ধরা পড়বে কিনা তা অনুমান করার DevTools-এর ক্ষমতা৷ আমরা অন্বেষণ করব কেন এটি এত কঠিন এবং কীভাবে V8 (Chrome-কে চালিত জাভাস্ক্রিপ্ট ইঞ্জিন) সাম্প্রতিক উন্নতিগুলি এটিকে আরও নির্ভুল করে তুলছে, একটি মসৃণ ডিবাগিং অভিজ্ঞতার দিকে নিয়ে যাচ্ছে৷
কেন ভবিষ্যদ্বাণী বিষয় ধরা
Chrome DevTools-এ, আপনার কাছে শুধুমাত্র ধরা না পড়া ব্যতিক্রমগুলির জন্য কোড এক্সিকিউশন পজ করার একটি বিকল্প আছে, যেগুলি ধরা হয়েছে সেগুলিকে এড়িয়ে গিয়ে৷
দৃশ্যের আড়ালে, প্রসঙ্গ সংরক্ষণ করার জন্য একটি ব্যতিক্রম ঘটলে ডিবাগার অবিলম্বে বন্ধ হয়ে যায়। এটি একটি ভবিষ্যদ্বাণী কারণ, এই মুহুর্তে, কোডে বিশেষ করে অ্যাসিঙ্ক্রোনাস পরিস্থিতিতে ব্যতিক্রম ধরা পড়বে কি না তা নিশ্চিতভাবে জানা অসম্ভব। এই অনিশ্চয়তা প্রোগ্রাম আচরণের ভবিষ্যদ্বাণী করার সহজাত অসুবিধা থেকে উদ্ভূত হয়, যা হল্টিং সমস্যার মতো।
নিম্নলিখিত উদাহরণ বিবেচনা করুন: ডিবাগার কোথায় বিরতি করা উচিত? (পরবর্তী বিভাগে একটি উত্তর খুঁজুন।)
async function inner() {
throw new Error(); // Should the debugger pause here?
}
async function outer() {
try {
const promise = inner();
// ...
await promise;
} catch (e) {
// ... or should the debugger pause here?
}
}
ডিবাগারে ব্যতিক্রমগুলিতে বিরতি বিঘ্নিত হতে পারে এবং ঘন ঘন বাধা সৃষ্টি করতে পারে এবং অপরিচিত কোডে যেতে পারে। এটি প্রশমিত করার জন্য, আপনি শুধুমাত্র ধরা না পড়া ব্যতিক্রমগুলি ডিবাগ করতে বেছে নিতে পারেন, যা প্রকৃত বাগগুলিকে সংকেত দেওয়ার সম্ভাবনা বেশি৷ যাইহোক, এটি ক্যাচ ভবিষ্যদ্বাণীর নির্ভুলতার উপর নির্ভর করে।
ভুল ভবিষ্যদ্বাণী হতাশার দিকে পরিচালিত করে:
- মিথ্যা নেতিবাচক ("অপরাধিত" ভবিষ্যদ্বাণী করা যখন এটি ধরা হবে)। ডিবাগারে অপ্রয়োজনীয় স্টপ।
- মিথ্যা ইতিবাচক ( "ধরা" ভবিষ্যদ্বাণী করা যখন এটি ধরা পড়বে না) । গুরুতর ত্রুটিগুলি ধরার সুযোগ মিস করা হয়েছে, সম্ভাব্যভাবে আপনাকে প্রত্যাশিতগুলি সহ সমস্ত ব্যতিক্রম ডিবাগ করতে বাধ্য করে৷
ডিবাগিং বাধা কমানোর আরেকটি পদ্ধতি হল উপেক্ষা তালিকা ব্যবহার করে, যা নির্দিষ্ট তৃতীয় পক্ষের কোডের মধ্যে ব্যতিক্রমগুলিতে বিরতি প্রতিরোধ করে। যাইহোক, সঠিক ক্যাচ ভবিষ্যদ্বাণী এখনও এখানে গুরুত্বপূর্ণ। যদি তৃতীয় পক্ষের কোড থেকে উদ্ভূত একটি ব্যতিক্রম পালিয়ে যায় এবং আপনার নিজের কোডকে প্রভাবিত করে, আপনি এটি ডিবাগ করতে সক্ষম হতে চাইবেন।
কিভাবে অ্যাসিঙ্ক্রোনাস কোড কাজ করে
প্রতিশ্রুতি, async
এবং await
এবং অন্যান্য অ্যাসিঙ্ক্রোনাস প্যাটার্নগুলি এমন পরিস্থিতির দিকে নিয়ে যেতে পারে যেখানে একটি ব্যতিক্রম বা প্রত্যাখ্যান, পরিচালনা করার আগে, একটি কার্যকরী পথ নিতে পারে যা একটি ব্যতিক্রম নিক্ষেপ করার সময় নির্ধারণ করা কঠিন। এর কারণ হল প্রতিশ্রুতি অপেক্ষা করা নাও হতে পারে বা এর আগে ব্যতিক্রম না হওয়া পর্যন্ত ক্যাচ হ্যান্ডলার যোগ করা হতে পারে। আসুন আমাদের আগের উদাহরণটি দেখি:
async function inner() {
throw new Error();
}
async function outer() {
try {
const promise = inner();
// ...
await promise;
} catch (e) {
// ...
}
}
এই উদাহরণে, outer()
প্রথমে inner()
কল করে যা অবিলম্বে একটি ব্যতিক্রম নিক্ষেপ করে। এটি থেকে ডিবাগার উপসংহারে আসতে পারে যে inner()
একটি প্রত্যাখ্যান প্রতিশ্রুতি ফিরিয়ে দেবে তবে বর্তমানে কিছুই অপেক্ষা করছে না বা অন্যথায় সেই প্রতিশ্রুতি পরিচালনা করছে। ডিবাগার অনুমান করতে পারে যে outer()
সম্ভবত এটির জন্য অপেক্ষা করবে এবং অনুমান করবে যে এটি তার বর্তমান try
ব্লকে এটি করবে এবং তাই এটি পরিচালনা করবে কিন্তু ডিবাগার প্রত্যাখ্যান প্রতিশ্রুতি ফিরে না আসা পর্যন্ত এবং await
বিবৃতিটি শেষ পর্যন্ত পৌঁছানো না হওয়া পর্যন্ত এটি সম্পর্কে নিশ্চিত হতে পারে না।
ডিবাগার এমন কোনো গ্যারান্টি দিতে পারে না যে ক্যাচ ভবিষ্যদ্বাণী সঠিক হবে কিন্তু এটি সঠিকভাবে ভবিষ্যদ্বাণী করার জন্য সাধারণ কোডিং প্যাটার্নের জন্য বিভিন্ন হিউরিস্টিক ব্যবহার করে। এই নিদর্শনগুলি বোঝার জন্য, প্রতিশ্রুতিগুলি কীভাবে কাজ করে তা শিখতে সহায়তা করে।
V8-এ, একটি জাভাস্ক্রিপ্ট Promise
একটি বস্তু হিসাবে উপস্থাপন করা হয় যা তিনটি অবস্থার একটিতে হতে পারে: পূরণ, প্রত্যাখ্যান বা মুলতুবি। যদি একটি প্রতিশ্রুতি পূর্ণ অবস্থায় থাকে এবং আপনি .then()
পদ্ধতিতে কল করেন, একটি নতুন মুলতুবি প্রতিশ্রুতি তৈরি করা হয় এবং একটি নতুন প্রতিশ্রুতি প্রতিক্রিয়া কাজ নির্ধারিত হয় যা হ্যান্ডলারকে চালাবে এবং তারপর হ্যান্ডলারের ফলাফলের সাথে প্রতিশ্রুতিটি পূরণে সেট করে বা হ্যান্ডলার একটি ব্যতিক্রম নিক্ষেপ করলে প্রত্যাখ্যানে সেট করে। আপনি যদি প্রত্যাখ্যান করা প্রতিশ্রুতিতে .catch()
পদ্ধতিতে কল করেন তবে একই ঘটনা ঘটে। বিপরীতে, একটি প্রত্যাখ্যাত প্রতিশ্রুতিতে .then()
বা পূর্ণ প্রতিশ্রুতিতে .catch()
কল করা একই অবস্থায় একটি প্রতিশ্রুতি ফিরিয়ে দেবে এবং হ্যান্ডলার চালাবে না।
একটি মুলতুবি প্রতিশ্রুতিতে একটি প্রতিক্রিয়া তালিকা রয়েছে যেখানে প্রতিটি প্রতিক্রিয়া বস্তুতে একটি পূরণ হ্যান্ডলার বা প্রত্যাখ্যান হ্যান্ডলার (বা উভয়) এবং একটি প্রতিক্রিয়া প্রতিশ্রুতি রয়েছে। সুতরাং একটি মুলতুবি প্রতিশ্রুতিতে .then()
কল করলে একটি পূর্ণ হ্যান্ডলারের সাথে একটি প্রতিক্রিয়া যোগ হবে এবং সেই সাথে প্রতিক্রিয়া প্রতিশ্রুতির জন্য একটি নতুন মুলতুবি প্রতিশ্রুতি যুক্ত হবে, যা .then()
ফিরে আসবে। .catch()
কল করলে অনুরূপ প্রতিক্রিয়া যোগ হবে কিন্তু একটি প্রত্যাখ্যান হ্যান্ডলারের সাথে। দুটি আর্গুমেন্ট সহ .then()
কল করা উভয় হ্যান্ডলারের সাথে একটি প্রতিক্রিয়া তৈরি করে এবং .finally()
কল করা বা প্রতিশ্রুতির জন্য অপেক্ষা করা দুটি হ্যান্ডলারের সাথে একটি প্রতিক্রিয়া যোগ করবে যা এই বৈশিষ্ট্যগুলি বাস্তবায়নের জন্য নির্দিষ্ট বিল্ট-ইন ফাংশন।
যখন মুলতুবি প্রতিশ্রুতি শেষ পর্যন্ত পূর্ণ বা প্রত্যাখ্যান করা হয়, তখন প্রতিক্রিয়া কাজগুলি তার সমস্ত পূর্ণ হ্যান্ডলার বা প্রত্যাখ্যান করা সমস্ত হ্যান্ডলারের জন্য নির্ধারিত হবে। সংশ্লিষ্ট প্রতিক্রিয়া প্রতিশ্রুতি আপডেট করা হবে, সম্ভাব্য তাদের নিজস্ব প্রতিক্রিয়া কাজ ট্রিগার.
উদাহরণ
নিম্নলিখিত কোড বিবেচনা করুন:
return new Promise(() => {throw new Error();})
.then(() => console.log('Never happened'))
.catch(() => console.log('Caught'));
এটা স্পষ্ট নাও হতে পারে যে এই কোডে তিনটি স্বতন্ত্র Promise
বিষয় জড়িত। উপরের কোডটি নিম্নলিখিত কোডের সমতুল্য:
const promise1 = new Promise(() => {throw new Error();});
const promise2 = promise1.then(() => console.log('Never happened'));
const promise3 = promise2.catch(() => console.log('Caught'));
return promise3;
এই উদাহরণে, নিম্নলিখিত পদক্ষেপগুলি ঘটবে:
-
Promise
নির্মাণকারী বলা হয়. - একটি নতুন মুলতুবি
Promise
তৈরি করা হয়েছে। - বেনামী ফাংশন চালানো হয়.
- একটি ব্যতিক্রম নিক্ষেপ করা হয়. এই মুহুর্তে, ডিবাগারকে থামাতে হবে কিনা তা সিদ্ধান্ত নিতে হবে।
- প্রতিশ্রুতি কনস্ট্রাক্টর এই ব্যতিক্রমটি ক্যাচ করে এবং তারপরে তার প্রতিশ্রুতির অবস্থাকে
rejected
করে তার মান থ্রো করা ত্রুটিতে সেট করে। এটি এই প্রতিশ্রুতি ফিরিয়ে দেয়, যাpromise1
এ সংরক্ষিত হয়। -
.then()
কোনো প্রতিক্রিয়া কাজের সময়সূচী নির্ধারণ করে না কারণpromise1
rejected
অবস্থায় রয়েছে। পরিবর্তে, একটি নতুন প্রতিশ্রুতি (promise2
) ফিরে আসে, যা একই ত্রুটি সহ প্রত্যাখ্যানিত অবস্থায়ও রয়েছে। -
.catch()
প্রদত্ত হ্যান্ডলার এবং একটি নতুন মুলতুবি প্রতিক্রিয়া প্রতিশ্রুতির সাথে একটি প্রতিক্রিয়া কাজ নির্ধারণ করে, যাpromise3
হিসাবে ফিরে আসে। এই মুহুর্তে ডিবাগার জানে ত্রুটিটি পরিচালনা করা হবে। - যখন প্রতিক্রিয়া টাস্কটি চলে, হ্যান্ডলারটি স্বাভাবিকভাবে ফিরে আসে এবং
promise3
এর অবস্থাটিfulfilled
করা হয়।
পরবর্তী উদাহরণের অনুরূপ কাঠামো রয়েছে তবে সম্পাদনটি একেবারেই আলাদা:
return Promise.resolve()
.then(() => {throw new Error();})
.then(() => console.log('Never happened'))
.catch(() => console.log('Caught'));
এটি এর সমতুল্য:
const promise1 = Promise.resolve();
const promise2 = promise1.then(() => {throw new Error();});
const promise3 = promise2.then(() => console.log('Never happened'));
const promise4 = promise3.catch(() => console.log('Caught'));
return promise4;
এই উদাহরণে, নিম্নলিখিত পদক্ষেপগুলি ঘটে:
- একটি
Promise
fulfilled
অবস্থায় তৈরি করা হয় এবংpromise1
এ সংরক্ষণ করা হয়। - প্রথম বেনামে ফাংশনটির সাথে একটি প্রতিশ্রুতি প্রতিক্রিয়া টাস্ক নির্ধারিত হয় এবং এর
(pending)
প্রতিক্রিয়া প্রতিশ্রুতিpromise2
হিসাবে ফিরে আসে। - একটি পরিপূর্ণ হ্যান্ডলার এবং এর প্রতিক্রিয়া প্রতিশ্রুতি সহ
promise2
এ একটি প্রতিক্রিয়া যুক্ত করা হয়, যাpromise3
হিসাবে ফিরে আসে। - প্রত্যাখ্যানিত হ্যান্ডলার এবং অন্য একটি প্রতিক্রিয়া প্রতিশ্রুতি সহ
promise3
তে একটি প্রতিক্রিয়া যুক্ত করা হয়, যাpromise4
হিসাবে ফিরে আসে। - দ্বিতীয় ধাপে নির্ধারিত প্রতিক্রিয়া টাস্কটি চালানো হয়।
- হ্যান্ডলার একটি ব্যতিক্রম ছুড়ে দেয়। এই মুহুর্তে ডিবাগারটি থামবে কি না তা সিদ্ধান্ত নিতে হবে। বর্তমানে হ্যান্ডলারটি আপনার একমাত্র চলমান জাভাস্ক্রিপ্ট কোড।
- যেহেতু টাস্কটি ব্যতিক্রমের সাথে শেষ হয়, সম্পর্কিত প্রতিক্রিয়া প্রতিশ্রুতি (
promise2
) প্রত্যাখ্যানিত রাষ্ট্রের কাছে সেট করা হয়েছে যার মানটি নিক্ষেপ করা ত্রুটিটি সেট করে। - যেহেতু
promise2
একটি প্রতিক্রিয়া ছিল, এবং সেই প্রতিক্রিয়াটির কোনও প্রত্যাখ্যান হ্যান্ডলার ছিল না, তাই এর প্রতিক্রিয়া প্রতিশ্রুতি (promise3
) একই ত্রুটি দিয়েrejected
করতে প্রস্তুত। - যেহেতু
promise3
একটি প্রতিক্রিয়া ছিল, এবং সেই প্রতিক্রিয়াটির একটি প্রত্যাখ্যাত হ্যান্ডলার ছিল, তাই সেই হ্যান্ডলার এবং এর প্রতিক্রিয়া প্রতিশ্রুতি (promise4
) এর সাথে একটি প্রতিশ্রুতি প্রতিক্রিয়া টাস্ক নির্ধারিত হয়েছে। - যখন সেই প্রতিক্রিয়া টাস্কটি চলে, হ্যান্ডলারটি সাধারণত ফিরে আসে এবং
promise4
এর অবস্থা পূরণ করতে পরিবর্তন করা হয়।
ক্যাচ পূর্বাভাসের জন্য পদ্ধতি
ক্যাচ পূর্বাভাসের জন্য তথ্যের দুটি সম্ভাব্য উত্স রয়েছে। একটি হ'ল কল স্ট্যাক। এটি সিঙ্ক্রোনাস ব্যতিক্রমগুলির জন্য সাউন্ড: ডিবাগার কল স্ট্যাকটি একইভাবে হাঁটতে পারে একইভাবে ব্যতিক্রম অনিচ্ছাকৃত কোডটি হবে এবং যদি এটি কোনও ফ্রেম খুঁজে পাওয়া যায় যেখানে এটি try...catch
ব্লকটি খুঁজে পাওয়া যায় তবে এটি বন্ধ হয়ে যায়। প্রতিশ্রুতি কনস্ট্রাক্টরগুলিতে বা অ্যাসিনক্রোনাস ফাংশনগুলিতে প্রত্যাখ্যানিত প্রতিশ্রুতি বা ব্যতিক্রমগুলির জন্য যা কখনও স্থগিত করা হয়নি, ডিবাগারও কল স্ট্যাকের উপর নির্ভর করে তবে এই ক্ষেত্রে, এর পূর্বাভাস সব ক্ষেত্রে নির্ভরযোগ্য হতে পারে না। এটি কারণ নিকটতম হ্যান্ডলারের ব্যতিক্রম ছুঁড়ে ফেলার পরিবর্তে অ্যাসিঙ্ক্রোনাস কোডটি একটি প্রত্যাখ্যানিত ব্যতিক্রম ফিরিয়ে দেবে এবং ডিবাগার অবশ্যই কলার এটি দিয়ে কী করবে সে সম্পর্কে কয়েকটি অনুমান করতে হবে।
প্রথমত, ডিবাগার ধরে নিয়েছে যে কোনও ফাংশন যা প্রত্যাবর্তিত প্রতিশ্রুতি গ্রহণ করে তা সম্ভবত সেই প্রতিশ্রুতি বা প্রাপ্ত প্রতিশ্রুতি ফিরিয়ে দিতে পারে যাতে স্ট্যাকের আরও উপরে অ্যাসিঙ্ক্রোনাস ফাংশনগুলির জন্য এটির জন্য অপেক্ষা করার সুযোগ থাকবে। দ্বিতীয়ত, ডিবাগার ধরে নিয়েছে যে যদি কোনও প্রতিশ্রুতি কোনও অ্যাসিঙ্ক্রোনাস ফাংশনে ফিরে আসে তবে এটি শীঘ্রই প্রথমে প্রবেশ না করে বা try...catch
ব্লক। এই অনুমানগুলির কোনওটিই সঠিক হওয়ার গ্যারান্টিযুক্ত নয় তবে তারা অ্যাসিঙ্ক্রোনাস ফাংশনগুলির সাথে সর্বাধিক সাধারণ কোডিং নিদর্শনগুলির জন্য সঠিক ভবিষ্যদ্বাণী করার জন্য যথেষ্ট। ক্রোম সংস্করণ 125-এ, আমরা আরও একটি হিউরিস্টিক যুক্ত .then()
: ডিবাগারটি পরীক্ষা করে যে কোনও কলি .catch()
.finally()
.catch()
.then()
.then()
এই ক্ষেত্রে, ডিবাগার ধরে নিয়েছে যে এগুলি আমরা যে প্রতিশ্রুতি দিচ্ছি তার পদ্ধতিগুলি বা এটির সাথে সম্পর্কিত একটি, তাই প্রত্যাখ্যানটি ধরা পড়বে।
তথ্যের দ্বিতীয় উত্স হ'ল প্রতিশ্রুতি প্রতিক্রিয়াগুলির গাছ। ডিবাগারটি একটি মূল প্রতিশ্রুতি দিয়ে শুরু হয়। কখনও কখনও এটি এমন একটি প্রতিশ্রুতি যার জন্য এর reject()
পদ্ধতিটি সবেমাত্র বলা হয়েছে। আরও সাধারণভাবে, যখন কোনও প্রতিশ্রুতি প্রতিক্রিয়া কাজের সময় কোনও ব্যতিক্রম বা প্রত্যাখ্যান ঘটে এবং কল স্ট্যাকের কোনও কিছুই এটি ধরতে দেখা যায় না, তখন ডিবাগারটি প্রতিক্রিয়ার সাথে যুক্ত প্রতিশ্রুতি থেকে সন্ধান করে। ডিবাগার মুলতুবি প্রতিশ্রুতিতে সমস্ত প্রতিক্রিয়া দেখায় এবং তাদের প্রত্যাখ্যান হ্যান্ডলারগুলি থাকে কিনা তা দেখে। যদি কোনও প্রতিক্রিয়া না দেয় তবে এটি প্রতিক্রিয়া প্রতিশ্রুতিটি দেখে এবং এটি থেকে পুনরাবৃত্তভাবে সনাক্ত করে। যদি সমস্ত প্রতিক্রিয়া চূড়ান্তভাবে প্রত্যাখ্যান হ্যান্ডলারের দিকে পরিচালিত করে, ডিবাগার প্রতিশ্রুতি প্রত্যাখ্যানকে ধরা পড়ার বিষয়টি বিবেচনা করে। কভার করার জন্য কিছু বিশেষ কেস রয়েছে, উদাহরণস্বরূপ, একটি .finally()
কলের জন্য অন্তর্নির্মিত প্রত্যাখ্যান হ্যান্ডলার গণনা না করে।
প্রতিশ্রুতি প্রতিক্রিয়া গাছ যদি তথ্য থাকে তবে সাধারণত তথ্যের একটি নির্ভরযোগ্য উত্স সরবরাহ করে। কিছু ক্ষেত্রে, Promise.reject()
কলের মতো Promise
অন্যান্য ক্ষেত্রে, প্রতিশ্রুতি প্রতিক্রিয়া গাছটিতে সাধারণত ক্যাচ ভবিষ্যদ্বাণীটি অনুমান করার জন্য প্রয়োজনীয় হ্যান্ডলারগুলি থাকে তবে এটি সর্বদা সম্ভব যে পরে আরও হ্যান্ডলারগুলি যুক্ত করা হবে যা ধরা থেকে অনাকাঙ্ক্ষিত বা তদ্বিপরীত ব্যতিক্রমকে পরিবর্তিত করবে। Promise.all/any/race
, যেখানে গোষ্ঠীর অন্যান্য প্রতিশ্রুতিগুলি প্রত্যাখ্যানকে কীভাবে চিকিত্সা করা হয় তা প্রভাবিত করতে পারে। এই পদ্ধতিগুলির জন্য, ডিবাগার ধরে নিয়েছে যে প্রতিশ্রুতি এখনও মুলতুবি থাকলে একটি প্রতিশ্রুতি প্রত্যাখ্যানকে ফরোয়ার্ড করা হবে।
নিম্নলিখিত দুটি উদাহরণ একবার দেখুন:
যদিও ধরা ব্যতিক্রমগুলির এই দুটি উদাহরণ একই রকম দেখাচ্ছে, তাদের জন্য বেশ আলাদা ক্যাচ পূর্বাভাস হিউরিস্টিকস প্রয়োজন। প্রথম উদাহরণে, একটি সমাধান করা প্রতিশ্রুতি তৈরি করা হয়, তারপরে .then()
এর জন্য একটি প্রতিক্রিয়া কাজ নির্ধারিত হয় যা একটি ব্যতিক্রম ছুঁড়ে ফেলবে, তারপরে .catch()
প্রতিক্রিয়া প্রতিশ্রুতিতে একটি প্রত্যাখ্যান হ্যান্ডলারকে সংযুক্ত করার জন্য ডাকা হয়। যখন প্রতিক্রিয়া টাস্কটি চালানো হয়, ব্যতিক্রমটি নিক্ষেপ করা হবে, এবং প্রতিশ্রুতি প্রতিক্রিয়া গাছটিতে ক্যাচ হ্যান্ডলার থাকবে, সুতরাং এটি ধরা হিসাবে সনাক্ত করা হবে। দ্বিতীয় উদাহরণে, ক্যাচ হ্যান্ডলার যুক্ত করার কোডটি চালানোর আগে প্রতিশ্রুতিটি তত্ক্ষণাত প্রত্যাখ্যান করা হয়, সুতরাং প্রতিশ্রুতির প্রতিক্রিয়া গাছটিতে কোনও প্রত্যাখ্যান হ্যান্ডলার নেই। ডিবাগারটি অবশ্যই কল স্ট্যাকটি দেখতে হবে তবে কোনও try...catch
। এটি সঠিকভাবে পূর্বাভাস দেওয়ার জন্য, ডিবাগারটি কোডের বর্তমান অবস্থানের আগে স্ক্যানগুলি .catch()
সারাংশ
আশা করি, এই ব্যাখ্যাটি ক্রোম ডেভটুলস, এর শক্তি এবং এর সীমাবদ্ধতাগুলিতে কীভাবে ক্যাচ পূর্বাভাস কাজ করে সে সম্পর্কে আলোকপাত করেছে। আপনি যদি ভুল ভবিষ্যদ্বাণীগুলির কারণে ডিবাগিংয়ের সমস্যার মুখোমুখি হন তবে এই বিকল্পগুলি বিবেচনা করুন:
- অ্যাসিঙ্ক ফাংশনগুলি ব্যবহার করার মতো ভবিষ্যদ্বাণী করার জন্য কোডিং প্যাটার্নটিকে আরও সোজা কিছুতে পরিবর্তন করুন।
- ডিভটুলগুলি যখন থামাতে ব্যর্থ হয় তবে সমস্ত ব্যতিক্রমগুলি ভাঙ্গতে নির্বাচন করুন।
- যদি ডিবাগারটি আপনি এটি চান না এমন কোথাও থামিয়ে দিচ্ছেন তবে "এখানে কখনই বিরতি দিন" ব্রেকপয়েন্ট বা শর্তাধীন ব্রেকপয়েন্ট ব্যবহার করুন।
স্বীকৃতি
আমাদের গভীর কৃতজ্ঞতা এই পোস্টটি সম্পাদনা করার জন্য তাদের অমূল্য সহায়তার জন্য সোফিয়া এমেলিয়ানোভা এবং জেসিলিন ইয়েনের কাছে চলে গেছে!
,ওয়েব অ্যাপ্লিকেশনগুলিতে ডিবাগিং ব্যতিক্রমগুলি সহজ বলে মনে হয়: কিছু ভুল হয়ে গেলে এবং তদন্ত করার সময় বিরতি কার্যকর করা। তবে জাভাস্ক্রিপ্টের অ্যাসিঙ্ক্রোনাস প্রকৃতি এটিকে আশ্চর্যজনকভাবে জটিল করে তোলে। প্রতিশ্রুতি এবং অ্যাসিঙ্ক্রোনাস ফাংশনগুলির মাধ্যমে ব্যতিক্রমগুলি উড়ে গেলে কখন এবং কোথায় বিরতি দিতে হবে তা ক্রোম ডেভটুলগুলি কীভাবে জানতে পারে?
এই পোস্টটি ক্যাচ পূর্বাভাসের চ্যালেঞ্জগুলিতে ডুব দেয় - আপনার কোডে পরে কোনও ব্যতিক্রম ধরা পড়বে কিনা তা অনুমান করার ডেভটুলসের ক্ষমতা। আমরা কেন এটি এত জটিল এবং ভি 8 (দ্য জাভাস্ক্রিপ্ট ইঞ্জিন পাওয়ারিং ক্রোম) এর সাম্প্রতিক উন্নতিগুলি এটিকে আরও নির্ভুল করে তুলছে, এটি একটি মসৃণ ডিবাগিং অভিজ্ঞতার দিকে পরিচালিত করে তা আমরা আবিষ্কার করব।
কেন ভবিষ্যদ্বাণী বিষয়গুলি ধরা
ক্রোম ডেভটুলসে, আপনার কাছে কেবল অনাকাঙ্ক্ষিত ব্যতিক্রমগুলির জন্য কোড এক্সিকিউশনটি বিরতি দেওয়ার বিকল্প রয়েছে, ধরা পড়ে এমনগুলি এড়িয়ে যাওয়া।
পর্দার আড়ালে, প্রসঙ্গটি সংরক্ষণের জন্য কোনও ব্যতিক্রম ঘটে তখন ডিবাগারটি তাত্ক্ষণিকভাবে থামে। এটি একটি ভবিষ্যদ্বাণী কারণ, এই মুহুর্তে, ব্যতিক্রমটি পরে কোডে ধরা পড়বে কি না, বিশেষত অ্যাসিঙ্ক্রোনাস পরিস্থিতিতে নিশ্চিতভাবে জানা অসম্ভব। এই অনিশ্চয়তা প্রোগ্রামের আচরণের পূর্বাভাস দেওয়ার অন্তর্নিহিত অসুবিধা থেকে শুরু করে, থামানো সমস্যার মতো।
নিম্নলিখিত উদাহরণটি বিবেচনা করুন: ডিবাগারটি কোথায় বিরতি দেওয়া উচিত? (পরবর্তী বিভাগে একটি উত্তর সন্ধান করুন))
async function inner() {
throw new Error(); // Should the debugger pause here?
}
async function outer() {
try {
const promise = inner();
// ...
await promise;
} catch (e) {
// ... or should the debugger pause here?
}
}
ডিবাগারে ব্যতিক্রমগুলিতে বিরতি দেওয়া বিঘ্নজনক হতে পারে এবং ঘন ঘন বাধা সৃষ্টি করে এবং অপরিচিত কোডে ঝাঁপিয়ে পড়ে। এটি প্রশমিত করার জন্য, আপনি কেবল অপ্রত্যাশিত ব্যতিক্রমগুলি ডিবাগ করতে বেছে নিতে পারেন, যা প্রকৃত বাগগুলির সংকেত দেওয়ার সম্ভাবনা বেশি। যাইহোক, এটি ক্যাচ পূর্বাভাসের যথার্থতার উপর নির্ভর করে।
ভুল ভবিষ্যদ্বাণীগুলি হতাশার দিকে পরিচালিত করে:
- মিথ্যা নেতিবাচক (যখন এটি ধরা পড়বে তখন "অনাকাঙ্ক্ষিত" পূর্বাভাস দেওয়া)। ডিবাগারে অপ্রয়োজনীয় স্টপস।
- মিথ্যা ধনাত্মক (যখন এটি অনাবৃত হবে তখন "ধরা" পূর্বাভাস দেওয়া)। সমালোচনামূলক ত্রুটিগুলি ধরার সুযোগ হাতছাড়া, সম্ভাব্যভাবে আপনাকে প্রত্যাশিত সমস্ত ব্যতিক্রম ডিবাগ করতে বাধ্য করে।
ডিবাগিং বাধা হ্রাস করার আরেকটি পদ্ধতি হ'ল উপেক্ষা তালিকাটি ব্যবহার করে, যা নির্দিষ্ট তৃতীয় পক্ষের কোডের মধ্যে ব্যতিক্রমগুলিতে বিরতি রোধ করে। তবে সঠিক ক্যাচ পূর্বাভাস এখনও এখানে গুরুত্বপূর্ণ। তৃতীয় পক্ষের কোডে উত্পন্ন ব্যতিক্রম যদি পালিয়ে যায় এবং আপনার নিজের কোডকে প্রভাবিত করে তবে আপনি এটি ডিবাগ করতে সক্ষম হতে চাইবেন।
কীভাবে অ্যাসিঙ্ক্রোনাস কোড কাজ করে
প্রতিশ্রুতি, async
এবং await
এবং অন্যান্য অ্যাসিঙ্ক্রোনাস নিদর্শনগুলি এমন পরিস্থিতিতে বাড়ে এমন একটি ব্যতিক্রম বা প্রত্যাখ্যান, পরিচালনা করার আগে, একটি এক্সিকিউশন পাথ নিতে পারে যা কোনও ব্যতিক্রম নিক্ষেপ করার সময় নির্ধারণ করা কঠিন। এটি কারণ যে প্রতিশ্রুতিগুলি অপেক্ষা করা নাও হতে পারে বা ব্যতিক্রম ইতিমধ্যে না হওয়া পর্যন্ত ক্যাচ হ্যান্ডলারগুলি যুক্ত করতে পারে। আসুন আমাদের আগের উদাহরণটি দেখুন:
async function inner() {
throw new Error();
}
async function outer() {
try {
const promise = inner();
// ...
await promise;
} catch (e) {
// ...
}
}
এই উদাহরণে, outer()
প্রথমে inner()
কল করে যা অবিলম্বে একটি ব্যতিক্রম ছুঁড়ে দেয়। এ থেকে ডিবাগার এই সিদ্ধান্তে পৌঁছাতে পারে যে inner()
একটি প্রত্যাখ্যানিত প্রতিশ্রুতি ফিরিয়ে দেবে তবে বর্তমানে কোনও কিছুই অপেক্ষা করছে না বা অন্যথায় সেই প্রতিশ্রুতি পরিচালনা করছে না। ডিবাগারটি অনুমান করতে পারে যে outer()
সম্ভবত এটির জন্য অপেক্ষা করবে এবং অনুমান করবে যে এটি তার বর্তমান try
ব্লকটিতে এটি করবে এবং তাই এটি পরিচালনা করবে তবে প্রত্যাখ্যানিত প্রতিশ্রুতি ফিরে না আসা পর্যন্ত ডিবাগার এটির বিষয়ে নিশ্চিত হতে পারে না এবং অবশেষে await
বিবৃতিটি পৌঁছেছে।
ডিবাগার এমন কোনও গ্যারান্টি দিতে পারে না যে ভবিষ্যদ্বাণীগুলি সঠিক হবে তবে এটি সঠিকভাবে পূর্বাভাস দেওয়ার জন্য সাধারণ কোডিং নিদর্শনগুলির জন্য বিভিন্ন ধরণের হিউরিস্টিক ব্যবহার করে। এই নিদর্শনগুলি বোঝার জন্য, প্রতিশ্রুতিগুলি কীভাবে কাজ করে তা শিখতে সহায়তা করে।
ভি 8 -তে, একটি জাভাস্ক্রিপ্ট Promise
এমন একটি বস্তু হিসাবে উপস্থাপিত হয় যা তিনটি রাজ্যের মধ্যে একটিতে হতে পারে: পরিপূর্ণ, প্রত্যাখ্যান করা বা মুলতুবি। যদি কোনও প্রতিশ্রুতি পরিপূর্ণ অবস্থায় থাকে এবং আপনি .then()
পদ্ধতিটি কল করেন তবে একটি নতুন মুলতুবি প্রতিশ্রুতি তৈরি করা হয় এবং একটি নতুন প্রতিশ্রুতি প্রতিক্রিয়া টাস্ক নির্ধারিত হয় যা হ্যান্ডলারটি চালাবে এবং তারপরে হ্যান্ডলারের ফলাফলের সাথে পূরণ করার প্রতিশ্রুতি নির্ধারণ করবে বা হ্যান্ডলার ব্যতিক্রম ছুঁড়ে ফেললে প্রত্যাখ্যান করার জন্য সেট করে। আপনি যদি প্রত্যাখ্যানিত প্রতিশ্রুতিতে .catch()
পদ্ধতিটি কল করেন তবে একই ঘটনা ঘটে। বিপরীতে, কলিং .then()
একটি প্রত্যাখ্যানিত প্রতিশ্রুতিতে বা .catch()
একটি মুলতুবি প্রতিশ্রুতিতে একটি প্রতিক্রিয়া তালিকা থাকে যেখানে প্রতিটি প্রতিক্রিয়া অবজেক্টে একটি পরিপূর্ণ হ্যান্ডলার বা প্রত্যাখ্যান হ্যান্ডলার (বা উভয়) এবং একটি প্রতিক্রিয়া প্রতিশ্রুতি থাকে। .then()
কলিং .then()
কলিং .catch()
একটি অনুরূপ প্রতিক্রিয়া যুক্ত করবে তবে প্রত্যাখ্যান হ্যান্ডলার সহ। দুটি .finally()
সহ কলিং .then()
যখন মুলতুবি প্রতিশ্রুতি শেষ পর্যন্ত পূরণ হয় বা প্রত্যাখ্যান করা হয়, তখন প্রতিক্রিয়া কাজগুলি তার সমস্ত পরিপূর্ণ হ্যান্ডলার বা এর সমস্ত প্রত্যাখ্যাত হ্যান্ডলারের জন্য নির্ধারিত হবে। সংশ্লিষ্ট প্রতিক্রিয়া প্রতিশ্রুতিগুলি তখন আপডেট করা হবে, সম্ভাব্যভাবে তাদের নিজস্ব প্রতিক্রিয়া কাজগুলি ট্রিগার করবে।
উদাহরণ
নিম্নলিখিত কোড বিবেচনা করুন:
return new Promise(() => {throw new Error();})
.then(() => console.log('Never happened'))
.catch(() => console.log('Caught'));
এটি স্পষ্ট নাও হতে পারে যে এই কোডটিতে তিনটি স্বতন্ত্র Promise
অবজেক্ট জড়িত। উপরের কোডটি নিম্নলিখিত কোডের সমতুল্য:
const promise1 = new Promise(() => {throw new Error();});
const promise2 = promise1.then(() => console.log('Never happened'));
const promise3 = promise2.catch(() => console.log('Caught'));
return promise3;
এই উদাহরণে, নিম্নলিখিত পদক্ষেপগুলি ঘটে:
-
Promise
কনস্ট্রাক্টর বলা হয়। - একটি নতুন মুলতুবি
Promise
তৈরি করা হয়। - বেনামে ফাংশনটি চালানো হয়।
- একটি ব্যতিক্রম নিক্ষেপ করা হয়। এই মুহুর্তে, ডিবাগারটি থামবে কি না তা সিদ্ধান্ত নিতে হবে।
- প্রতিশ্রুতি কনস্ট্রাক্টর এই ব্যতিক্রমটি ধরেন এবং তারপরে নিক্ষিপ্ত ত্রুটিতে তার মান সেট দিয়ে
rejected
করার প্রতিশ্রুতিটির অবস্থা পরিবর্তন করে। এটি এই প্রতিশ্রুতি দেয়, যাpromise1
এ সঞ্চিত রয়েছে। -
.then()
promise1
rejected
পরিবর্তে, একটি নতুন প্রতিশ্রুতি (promise2
) ফিরে আসে, যা একই ত্রুটি সহ প্রত্যাখ্যানিত অবস্থায়ও রয়েছে। -
.catch()
প্রদত্ত হ্যান্ডলার এবং একটি নতুন মুলতুবি প্রতিক্রিয়া প্রতিশ্রুতির সাথে একটি প্রতিক্রিয়া কাজ নির্ধারণ করে, যাpromise3
হিসাবে ফিরে আসে। এই মুহুর্তে ডিবাগার জানে ত্রুটিটি পরিচালনা করা হবে। - যখন প্রতিক্রিয়া টাস্কটি চলে, হ্যান্ডলারটি স্বাভাবিকভাবে ফিরে আসে এবং
promise3
এর অবস্থাটিfulfilled
করা হয়।
পরবর্তী উদাহরণের অনুরূপ কাঠামো রয়েছে তবে সম্পাদনটি একেবারেই আলাদা:
return Promise.resolve()
.then(() => {throw new Error();})
.then(() => console.log('Never happened'))
.catch(() => console.log('Caught'));
এটি এর সমতুল্য:
const promise1 = Promise.resolve();
const promise2 = promise1.then(() => {throw new Error();});
const promise3 = promise2.then(() => console.log('Never happened'));
const promise4 = promise3.catch(() => console.log('Caught'));
return promise4;
এই উদাহরণে, নিম্নলিখিত পদক্ষেপগুলি ঘটে:
- একটি
Promise
fulfilled
অবস্থায় তৈরি করা হয় এবংpromise1
এ সংরক্ষণ করা হয়। - প্রথম বেনামে ফাংশনটির সাথে একটি প্রতিশ্রুতি প্রতিক্রিয়া টাস্ক নির্ধারিত হয় এবং এর
(pending)
প্রতিক্রিয়া প্রতিশ্রুতিpromise2
হিসাবে ফিরে আসে। - একটি পরিপূর্ণ হ্যান্ডলার এবং এর প্রতিক্রিয়া প্রতিশ্রুতি সহ
promise2
এ একটি প্রতিক্রিয়া যুক্ত করা হয়, যাpromise3
হিসাবে ফিরে আসে। - প্রত্যাখ্যানিত হ্যান্ডলার এবং অন্য একটি প্রতিক্রিয়া প্রতিশ্রুতি সহ
promise3
তে একটি প্রতিক্রিয়া যুক্ত করা হয়, যাpromise4
হিসাবে ফিরে আসে। - দ্বিতীয় ধাপে নির্ধারিত প্রতিক্রিয়া টাস্কটি চালানো হয়।
- হ্যান্ডলার একটি ব্যতিক্রম ছুড়ে দেয়। এই মুহুর্তে ডিবাগারটি থামবে কি না তা সিদ্ধান্ত নিতে হবে। বর্তমানে হ্যান্ডলারটি আপনার একমাত্র চলমান জাভাস্ক্রিপ্ট কোড।
- যেহেতু টাস্কটি ব্যতিক্রমের সাথে শেষ হয়, সম্পর্কিত প্রতিক্রিয়া প্রতিশ্রুতি (
promise2
) প্রত্যাখ্যানিত রাষ্ট্রের কাছে সেট করা হয়েছে যার মানটি নিক্ষেপ করা ত্রুটিটি সেট করে। - যেহেতু
promise2
একটি প্রতিক্রিয়া ছিল, এবং সেই প্রতিক্রিয়াটির কোনও প্রত্যাখ্যান হ্যান্ডলার ছিল না, তাই এর প্রতিক্রিয়া প্রতিশ্রুতি (promise3
) একই ত্রুটি দিয়েrejected
করতে প্রস্তুত। - যেহেতু
promise3
একটি প্রতিক্রিয়া ছিল, এবং সেই প্রতিক্রিয়াটির একটি প্রত্যাখ্যাত হ্যান্ডলার ছিল, তাই সেই হ্যান্ডলার এবং এর প্রতিক্রিয়া প্রতিশ্রুতি (promise4
) এর সাথে একটি প্রতিশ্রুতি প্রতিক্রিয়া টাস্ক নির্ধারিত হয়েছে। - যখন সেই প্রতিক্রিয়া টাস্কটি চলে, হ্যান্ডলারটি সাধারণত ফিরে আসে এবং
promise4
এর অবস্থা পূরণ করতে পরিবর্তন করা হয়।
ক্যাচ পূর্বাভাসের জন্য পদ্ধতি
ক্যাচ পূর্বাভাসের জন্য তথ্যের দুটি সম্ভাব্য উত্স রয়েছে। একটি হ'ল কল স্ট্যাক। এটি সিঙ্ক্রোনাস ব্যতিক্রমগুলির জন্য সাউন্ড: ডিবাগার কল স্ট্যাকটি একইভাবে হাঁটতে পারে একইভাবে ব্যতিক্রম অনিচ্ছাকৃত কোডটি হবে এবং যদি এটি কোনও ফ্রেম খুঁজে পাওয়া যায় যেখানে এটি try...catch
ব্লকটি খুঁজে পাওয়া যায় তবে এটি বন্ধ হয়ে যায়। প্রতিশ্রুতি কনস্ট্রাক্টরগুলিতে বা অ্যাসিনক্রোনাস ফাংশনগুলিতে প্রত্যাখ্যানিত প্রতিশ্রুতি বা ব্যতিক্রমগুলির জন্য যা কখনও স্থগিত করা হয়নি, ডিবাগারও কল স্ট্যাকের উপর নির্ভর করে তবে এই ক্ষেত্রে, এর পূর্বাভাস সব ক্ষেত্রে নির্ভরযোগ্য হতে পারে না। এটি কারণ নিকটতম হ্যান্ডলারের ব্যতিক্রম ছুঁড়ে ফেলার পরিবর্তে অ্যাসিঙ্ক্রোনাস কোডটি একটি প্রত্যাখ্যানিত ব্যতিক্রম ফিরিয়ে দেবে এবং ডিবাগার অবশ্যই কলার এটি দিয়ে কী করবে সে সম্পর্কে কয়েকটি অনুমান করতে হবে।
প্রথমত, ডিবাগার ধরে নিয়েছে যে কোনও ফাংশন যা প্রত্যাবর্তিত প্রতিশ্রুতি গ্রহণ করে তা সম্ভবত সেই প্রতিশ্রুতি বা প্রাপ্ত প্রতিশ্রুতি ফিরিয়ে দিতে পারে যাতে স্ট্যাকের আরও উপরে অ্যাসিঙ্ক্রোনাস ফাংশনগুলির জন্য এটির জন্য অপেক্ষা করার সুযোগ থাকবে। দ্বিতীয়ত, ডিবাগার ধরে নিয়েছে যে যদি কোনও প্রতিশ্রুতি কোনও অ্যাসিঙ্ক্রোনাস ফাংশনে ফিরে আসে তবে এটি শীঘ্রই প্রথমে প্রবেশ না করে বা try...catch
ব্লক। এই অনুমানগুলির কোনওটিই সঠিক হওয়ার গ্যারান্টিযুক্ত নয় তবে তারা অ্যাসিঙ্ক্রোনাস ফাংশনগুলির সাথে সর্বাধিক সাধারণ কোডিং নিদর্শনগুলির জন্য সঠিক ভবিষ্যদ্বাণী করার জন্য যথেষ্ট। ক্রোম সংস্করণ 125-এ, আমরা আরও একটি হিউরিস্টিক যুক্ত .then()
: ডিবাগারটি পরীক্ষা করে যে কোনও কলি .catch()
.finally()
.catch()
.then()
.then()
এই ক্ষেত্রে, ডিবাগার ধরে নিয়েছে যে এগুলি আমরা যে প্রতিশ্রুতি দিচ্ছি তার পদ্ধতিগুলি বা এটির সাথে সম্পর্কিত একটি, তাই প্রত্যাখ্যানটি ধরা পড়বে।
তথ্যের দ্বিতীয় উত্স হ'ল প্রতিশ্রুতি প্রতিক্রিয়াগুলির গাছ। ডিবাগারটি একটি মূল প্রতিশ্রুতি দিয়ে শুরু হয়। কখনও কখনও এটি এমন একটি প্রতিশ্রুতি যার জন্য এর reject()
পদ্ধতিটি সবেমাত্র বলা হয়েছে। আরও সাধারণভাবে, যখন কোনও প্রতিশ্রুতি প্রতিক্রিয়া কাজের সময় কোনও ব্যতিক্রম বা প্রত্যাখ্যান ঘটে এবং কল স্ট্যাকের কোনও কিছুই এটি ধরতে দেখা যায় না, তখন ডিবাগারটি প্রতিক্রিয়ার সাথে যুক্ত প্রতিশ্রুতি থেকে সন্ধান করে। ডিবাগার মুলতুবি প্রতিশ্রুতিতে সমস্ত প্রতিক্রিয়া দেখায় এবং তাদের প্রত্যাখ্যান হ্যান্ডলারগুলি থাকে কিনা তা দেখে। যদি কোনও প্রতিক্রিয়া না দেয় তবে এটি প্রতিক্রিয়া প্রতিশ্রুতিটি দেখে এবং এটি থেকে পুনরাবৃত্তভাবে সনাক্ত করে। যদি সমস্ত প্রতিক্রিয়া চূড়ান্তভাবে প্রত্যাখ্যান হ্যান্ডলারের দিকে পরিচালিত করে, ডিবাগার প্রতিশ্রুতি প্রত্যাখ্যানকে ধরা পড়ার বিষয়টি বিবেচনা করে। কভার করার জন্য কিছু বিশেষ কেস রয়েছে, উদাহরণস্বরূপ, একটি .finally()
কলের জন্য অন্তর্নির্মিত প্রত্যাখ্যান হ্যান্ডলার গণনা না করে।
প্রতিশ্রুতি প্রতিক্রিয়া গাছ যদি তথ্য থাকে তবে সাধারণত তথ্যের একটি নির্ভরযোগ্য উত্স সরবরাহ করে। কিছু ক্ষেত্রে, Promise.reject()
কলের মতো Promise
অন্যান্য ক্ষেত্রে, প্রতিশ্রুতি প্রতিক্রিয়া গাছটিতে সাধারণত ক্যাচ ভবিষ্যদ্বাণীটি অনুমান করার জন্য প্রয়োজনীয় হ্যান্ডলারগুলি থাকে তবে এটি সর্বদা সম্ভব যে পরে আরও হ্যান্ডলারগুলি যুক্ত করা হবে যা ধরা থেকে অনাকাঙ্ক্ষিত বা তদ্বিপরীত ব্যতিক্রমকে পরিবর্তিত করবে। Promise.all/any/race
, যেখানে গোষ্ঠীর অন্যান্য প্রতিশ্রুতিগুলি প্রত্যাখ্যানকে কীভাবে চিকিত্সা করা হয় তা প্রভাবিত করতে পারে। এই পদ্ধতিগুলির জন্য, ডিবাগার ধরে নিয়েছে যে প্রতিশ্রুতি এখনও মুলতুবি থাকলে একটি প্রতিশ্রুতি প্রত্যাখ্যানকে ফরোয়ার্ড করা হবে।
নিম্নলিখিত দুটি উদাহরণ একবার দেখুন:
যদিও ধরা ব্যতিক্রমগুলির এই দুটি উদাহরণ একই রকম দেখাচ্ছে, তাদের জন্য বেশ আলাদা ক্যাচ পূর্বাভাস হিউরিস্টিকস প্রয়োজন। প্রথম উদাহরণে, একটি সমাধান করা প্রতিশ্রুতি তৈরি করা হয়, তারপরে .then()
এর জন্য একটি প্রতিক্রিয়া কাজ নির্ধারিত হয় যা একটি ব্যতিক্রম ছুঁড়ে ফেলবে, তারপরে .catch()
প্রতিক্রিয়া প্রতিশ্রুতিতে একটি প্রত্যাখ্যান হ্যান্ডলারকে সংযুক্ত করার জন্য ডাকা হয়। যখন প্রতিক্রিয়া টাস্কটি চালানো হয়, ব্যতিক্রমটি নিক্ষেপ করা হবে, এবং প্রতিশ্রুতি প্রতিক্রিয়া গাছটিতে ক্যাচ হ্যান্ডলার থাকবে, সুতরাং এটি ধরা হিসাবে সনাক্ত করা হবে। দ্বিতীয় উদাহরণে, ক্যাচ হ্যান্ডলার যুক্ত করার কোডটি চালানোর আগে প্রতিশ্রুতিটি তত্ক্ষণাত প্রত্যাখ্যান করা হয়, সুতরাং প্রতিশ্রুতির প্রতিক্রিয়া গাছটিতে কোনও প্রত্যাখ্যান হ্যান্ডলার নেই। ডিবাগারটি অবশ্যই কল স্ট্যাকটি দেখতে হবে তবে কোনও try...catch
। এটি সঠিকভাবে পূর্বাভাস দেওয়ার জন্য, ডিবাগারটি কোডের বর্তমান অবস্থানের আগে স্ক্যানগুলি .catch()
সারাংশ
আশা করি, এই ব্যাখ্যাটি ক্রোম ডেভটুলস, এর শক্তি এবং এর সীমাবদ্ধতাগুলিতে কীভাবে ক্যাচ পূর্বাভাস কাজ করে সে সম্পর্কে আলোকপাত করেছে। আপনি যদি ভুল ভবিষ্যদ্বাণীগুলির কারণে ডিবাগিংয়ের সমস্যার মুখোমুখি হন তবে এই বিকল্পগুলি বিবেচনা করুন:
- অ্যাসিঙ্ক ফাংশনগুলি ব্যবহার করার মতো ভবিষ্যদ্বাণী করার জন্য কোডিং প্যাটার্নটিকে আরও সোজা কিছুতে পরিবর্তন করুন।
- ডিভটুলগুলি যখন থামাতে ব্যর্থ হয় তবে সমস্ত ব্যতিক্রমগুলি ভাঙ্গতে নির্বাচন করুন।
- যদি ডিবাগারটি আপনি এটি চান না এমন কোথাও থামিয়ে দিচ্ছেন তবে "এখানে কখনই বিরতি দিন" ব্রেকপয়েন্ট বা শর্তাধীন ব্রেকপয়েন্ট ব্যবহার করুন।
স্বীকৃতি
আমাদের গভীর কৃতজ্ঞতা এই পোস্টটি সম্পাদনা করার জন্য তাদের অমূল্য সহায়তার জন্য সোফিয়া এমেলিয়ানোভা এবং জেসিলিন ইয়েনের কাছে চলে গেছে!