জাভাস্ক্রিপ্ট কৌতূহল প্রতিশ্রুতি


96

আমি যখন এই প্রতিশ্রুতি কল করি তখন আউটপুট ফাংশন কলগুলির ক্রমের সাথে মেলে না। এর .thenআগে আসে .catch, যদিও প্রতিশ্রুতি .thenপরে ডাকা হয়েছিল। এর কারণ কী?

const verifier = (a, b) =>
  new Promise((resolve, reject) => (a > b ? resolve(true) : reject(false)));

verifier(3, 4)
  .then((response) => console.log("response: ", response))
  .catch((error) => console.log("error: ", error));

verifier(5, 4)
  .then((response) => console.log("response: ", response))
  .catch((error) => console.log("error: ", error));

আউটপুট

node promises.js
response: true
error: false

34
আপনার প্রতিশ্রুতিগুলির স্বাধীন শৃঙ্খলের মধ্যে কখনই নির্ভর করা উচিত নয়।
বার্গি

উত্তর:


136

এর নীচে পৌঁছানোর জন্য এটি একটি দুর্দান্ত প্রশ্ন।

আপনি যখন এটি করবেন:

verifier(3,4).then(...)

এটি নতুন প্রতিশ্রুতি দেয় যা নতুন প্রত্যাশিত প্রতিশ্রুতি .catch()অনুসরণকারী হ্যান্ডলারটি চালাতে পারে তার আগে ইভেন্ট লুপটিতে আবার একটি চক্র প্রয়োজন requires এই অতিরিক্ত চক্রটি পরবর্তী ক্রম দেয়:

verifier(5,4).then(...)

.then()পূর্ববর্তী লাইনের আগে এর হ্যান্ডলারটি চালনার একটি সুযোগ .catch()কারণ .catch()হ্যান্ডলারটি প্রথম থেকে কাতায় আসার আগে এটি ইতিমধ্যে সারিতে ছিল এবং ফিফু ক্রমে আইটেমগুলি কাতার থেকে চালানো হয়।


দ্রষ্টব্য, আপনি যদি .then(f1, f2)ফর্মটি স্থলে ব্যবহার করেন তবে .then().catch()এটির প্রত্যাশা করা হলে এটি চলবে কারণ কোনও অতিরিক্ত প্রতিশ্রুতি নেই এবং এইভাবে কোনও অতিরিক্ত টিক জড়িত নেই:

const verifier = (a, b) =>
  new Promise((resolve, reject) => (a > b ? resolve(true) : reject(false)));

verifier(3, 4)
  .then((response) => console.log("response (3,4): ", response),
        (error) => console.log("error (3,4): ", error)
  );

verifier(5, 4)
  .then((response) => console.log("response (5,4): ", response))
  .catch((error) => console.log("error (5,4): ", error));

দ্রষ্টব্য, আমি সমস্ত বার্তাগুলির লেবেলও রেখেছি যাতে আপনি দেখতে পান যে কোন verifier()কলটি এসেছে যার ফলে আউটপুটটি পড়া খুব সহজ হয়ে যায়।


প্রতিশ্রুতি কলব্যাকিং ক্রম এবং আরও বিশদ ব্যাখ্যায় ES6 স্পেক

ES6 বৈশিষ্টটি আমাদের জানায় যে প্রতিশ্রুতি "কাজগুলি" (যেমন এটি একটি .then()বা একটি কলব্যাক কল করে .catch()) ফিফু ক্রমে চালিত হয় যখন তারা চাকরীর কাতারে প্রবেশ করানো হয়। এটি বিশেষত ফিফোর নাম দেয় না, তবে এটি নির্দিষ্ট করে যে কাতার শেষে নতুন কাজ সন্নিবেশ করা হয়েছে এবং সারি শুরু থেকেই চাকরীগুলি চালিত হয়। এটি FIFO ক্রম প্রয়োগ করে।

পারফর্মপ্রোমাইসথেন (যা থেকে কলব্যাক কার্যকর করে .then()) এনকুইজবকে নিয়ে যাবে যা সমাধান বা প্রত্যাখ্যান হ্যান্ডলারটি কীভাবে বাস্তবায়িত হবে তা নির্ধারিত হয়ে যায়। এনকুইজব নির্দিষ্ট করে যে মুলতুবি থাকা কাজটি কাজের সারির পিছনে যুক্ত করা হয়েছে। তারপরে নেক্সটজব অপারেশন আইটেমটি সারির সামনে থেকে টেনে নেয়। এটি প্রতিশ্রুতি কাজের সারি থেকে চাকরির সার্ভিসে ফিফোর আদেশ নিশ্চিত করে।

সুতরাং, আসল প্রশ্নের উদাহরণে, আমরা verifier(3,4)প্রতিশ্রুতি এবং প্রতিশ্রুতিটির জন্য কল-ব্যাকগুলি পেয়েছি verifier(5,4)যাতে তারা যে ক্রমটি চালিত হয়েছিল সেভাবে কাজের সারিতে সন্নিবেশ করানো হয়েছে কারণ এই দুটি আসল প্রতিশ্রুতিই সম্পন্ন হয়েছে। তারপরে, দোভাষী যখন ইভেন্টের লুপটিতে ফিরে আসেন, তখন এটি প্রথমে verifier(3,4)কাজ শুরু করে। এই প্রতিশ্রুতি প্রত্যাখ্যান করা হয়েছে এবং এর জন্য কোনও কলব্যাক নেই verifier(3,4).then(...)। সুতরাং, এটি যা করে তা প্রতিশ্রুতি প্রত্যাখ্যান করে যা verifier(3,4).then(...)প্রত্যাবর্তন করে এবং এর ফলে verifier(3,4).then(...).catch(...)হ্যান্ডলারটি জবকিউতে সন্নিবেশিত করে।

তারপরে, এটি ইভেন্ট লুপে ফিরে যায় এবং পরবর্তী কাজ এটি জবকিউ থেকে টানা verifier(5, 4)কাজ হয়। এটির একটি সমাধান প্রতিশ্রুতি এবং একটি সমাধান হ্যান্ডলার রয়েছে যাতে এটি হ্যান্ডলারটিকে কল করে। এর ফলে response (5,4):আউটপুট প্রদর্শিত হবে।

তারপরে, এটি ইভেন্ট লুপটিতে ফিরে যায় এবং পরবর্তী কাজটি এটি জবকিউ থেকে টানা হয় এমন verifier(3,4).then(...).catch(...)কাজটি যেখানে এটি চালায় এবং এর ফলে error (3,4)আউটপুট প্রদর্শিত হবে।

এটি কারণ কারণ .catch()1 ম শৃঙ্খলাটি তার চেইনের .then()মধ্যে 2 য় চেইনের তুলনায় এর প্রতিশ্রুতি স্তর আরও গভীর যা আপনার প্রতিবেদনের ক্রম ঘটায় causes এবং, কারণ প্রতিশ্রুতি শৃঙ্খলাগুলি এক সাথে পর্যায়ক্রমে FIFO ক্রমের কাজের সারি হয়ে এক স্তর থেকে পরের দিকে গিয়েছে, সুসংগতভাবে নয়।


তফসিল বিবরণের এই স্তরের উপর নির্ভর করার বিষয়ে সাধারণ পরামর্শ

এফওয়াইআই, সাধারণভাবে, আমি কোডটি লেখার চেষ্টা করি যা বিস্তারিত সময় সম্পর্কিত জ্ঞানের এই স্তরের উপর নির্ভর করে না। যদিও এটি কৌতূহলী এবং মাঝে মাঝে বোঝার জন্য দরকারী, এটি কোড হিসাবে ভঙ্গুর কোড হিসাবে একটি আপাতদৃষ্টিতে আপোষহীন পরিবর্তন আপেক্ষিক সময় পরিবর্তনের দিকে নিয়ে যেতে পারে frag সুতরাং, যদি টাইমিংয়ের মতো দুটি শৃঙ্খলের মধ্যে সমালোচনা হয়, তবে আমি বরং কোডটি এমনভাবে লিখতে চাই যাতে এই সময়ের সাথে বোঝার উপায়টির উপর নির্ভর না করে সময়কে যেভাবে চান তা করতে বাধ্য করে।


আরও সুনির্দিষ্টভাবে বলতে গেলে, এই সঠিক আচরণটি প্রতিশ্রুতিগুলির নির্দিষ্টকরণের কোথাও নথিভুক্ত করা হয়নি যা এটি বাস্তবায়নের বিশদ করে তোলে। আপনি দোভাষী (উদাহরণস্বরূপ নোড.জেএস বনাম এজ বনাম ফায়ারফক্স) এর মধ্যে বা দোভাষীদের সংস্করণগুলির মধ্যে (যেমন: নোড 12 বনাম নোড 14) এর মধ্যে আলাদা আচরণ পেতে পারেন। এই অনুমানটি কেবল বলেছে যে জালগো কোড এড়াতে প্রতিশ্রুতিগুলি অবিচ্ছিন্নভাবে প্রক্রিয়া করা হয় (যা আইএমএইচও বিটিডব্লিউকে বিভ্রান্ত করেছিল কারণ এটি এমন লোকদের দ্বারা অনুপ্রাণিত হয়েছিল যারা সম্ভাব্য
অ্যাসিনক্রোনাস

@ স্লেবেটম্যান - এটি কি নথিবদ্ধ নয় যে পৃথক প্রতিশ্রুতি থেকে প্রাপ্ত প্রতিশ্রুতি কলব্যাকগুলিকে যখন কাতারে প্রবেশ করা হয়েছিল এবং পরবর্তী টিক পর্যন্ত চালানো যায় না তার ভিত্তিতে তাকে ফিফো বলা হয়? দেখে মনে হয় যে ফিফোর অর্ডার এখানে যা প্রয়োজন তা হ'ল কারণ .then()একটি নতুন প্রতিশ্রুতি ফেরত দিতে হবে যা ভবিষ্যতের টিকের উপরই অ্যাসিঙ্ক্রোনালি সমাধান করতে / প্রত্যাখ্যান করতে হবে যা এই আদেশের দিকে নিয়ে যায়। প্রতিযোগী কলব্যাকের ফিফো অর্ডার ব্যবহার না করে এমন কোনও বাস্তবায়ন সম্পর্কে আপনি কি জানেন?
jفر00

4
@ স্লেবেটম্যান প্রতিশ্রুতি / এ + এটি নির্দিষ্ট করে না। ES6 এটি নির্দিষ্ট করে। ( awaitযদিও ES11 এর আচরণ পরিবর্তন করেছে )।
বার্গি

কুইউং অর্ডারে ইএস 6 স্পেস থেকে। PerformPromiseThenহতে হবে EnqueueJobকীভাবে সমাধান বা প্রত্যাখ্যান হ্যান্ডলার বলা যেতে নির্ধারিত পরার। এনকুইজব নির্দিষ্ট করে যে মুলতুবি থাকা কাজটি কাজের সারির পিছনে যুক্ত করা হয়েছে। তারপরে নেক্সটজব অপারেশন আইটেমটি সারির সামনে থেকে টেনে নেয়। এটি প্রতিশ্রুতি কাজের সারিতে ফিফোর আদেশ নিশ্চিত করে।
jفر00

@ বারগি ইএস 11-এ এই পরিবর্তনটি কী await? একটি লিঙ্ক যথেষ্ট। ধন্যবাদ !!
পেড্রো এ

49

Promise.resolve()
  .then(() => console.log('a1'))
  .then(() => console.log('a2'))
  .then(() => console.log('a3'))
Promise.resolve()
  .then(() => console.log('b1'))
  .then(() => console.log('b2'))
  .then(() => console.log('b3'))

আউটপুট এ 1, এ 2, এ 3, বি 1, বি 2, বি 3 এর পরিবর্তে আপনি এ 1, বি 1, এ 2, বি 2, এ 3, বি 3 দেখতে পাবেন কারণ একই কারণে - প্রতিটির পরে প্রতিশ্রুতি ফিরে আসে এবং এটি ইভেন্ট-লুপের শেষে চলে যায় কিউ. সুতরাং আমরা এই "প্রতিশ্রুতি রেস" দেখতে পারি। কিছু নেস্টেড প্রতিশ্রুতি আছে যখন একই।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.