+ = দিয়ে অ্যাসিঙ্ক ফাংশন


63

let x = 0;

async function test() {
    x += await 5;
    console.log('x :', x);
}

test();
x += 1;
console.log('x :', x);

মান xলগ ইন করা হয় 1এবং 5। আমার প্রশ্ন: x 5দ্বিতীয় লগের মান কেন ?

যদি testপরে মৃত্যুদন্ড কার্যকর করা হয় x += 1(যেহেতু এটি একটি অ্যাসিঙ্ক ফাংশন) তবে এক্স এর সময় testনির্বাহের সময় 1 হবে , সুতরাং x += await 5এর মান করা উচিত x 6


1
আপনার অবশ্যই অবশ্যই await (x += 5) এবং এর মধ্যে পার্থক্যটি জানতে হবে x += await 5
সিংহি জন

উত্তর:


60

টি এল; ডিআর: কারণ +=সার্চ xআগে, কিন্তু এটা লিখেছেন পর পরিবর্তিত হয়েছে, কারণে awaitতার দ্বিতীয় প্রতীক (ডান দিকে) এ শব্দ।


asyncপ্রথম awaitবিবৃতি না হওয়া পর্যন্ত তারা যখন কল করে ততক্ষণে ফাংশনগুলি সিঙ্ক্রোনজ হয় ।

সুতরাং, যদি আপনি অপসারণ করেন তবে awaitএটি একটি সাধারণ ফাংশনের মতো আচরণ করে (ব্যতিক্রমটি এটি এখনও প্রতিশ্রুতি দেয়)।

সেক্ষেত্রে , আপনি কনসোলে 5এবং পেয়ে 6যাবেন:

let x = 0;

async function test() {
  x += 5;
  console.log('x :', x);
}

test();
x += 1;
console.log('x :', x);

প্রথমটি awaitসমকালীন চলমান বন্ধ করে দেয়, এমনকি যদি তার যুক্তি সুসংগতভাবে উপলব্ধ হয় তবে নিম্নলিখিতটি ফিরে আসবে 1এবং 6যেমনটি আপনি প্রত্যাশা করেছেন:

let x = 0;

async function test() {
  // Enter asynchrony
  await 0;

  x += 5;
  console.log('x :', x);
}

test();
x += 1;
console.log('x :', x);

তবে আপনার ক্ষেত্রে কিছুটা জটিল।

আপনি awaitএকটি প্রকাশের ভিতরে রেখেছেন , এটি ব্যবহার করে +=

আপনি সম্ভবত জানেন, যে জেএস x += yঅনুরূপ x = (x + y)। আমি আরও ভাল বোঝার জন্য পরবর্তী ফর্মটি ব্যবহার করব:

let x = 0;

async function test() {
  x = (x + await 5);
  console.log('x :', x);
}

test();
x += 1;
console.log('x :', x);

দোভাষী যখন এই লাইনে পৌঁছান ...

x = (x + await 5);

... এটি এর মূল্যায়ন শুরু করে, এবং এটি ...

x = (0 + await 5);

... তারপর, এটি পৌঁছে যায় awaitএবং থামে।

ফাংশন কল করার পরে কোডটি চলতে শুরু করে এবং এর মানটি সংশোধন করে x, তারপরে এটি লগ করে।

xএখন 1

তারপরে, মূল স্ক্রিপ্টটি প্রস্থান করার পরে, দোভাষী আবার বিরামপ্রাপ্ত testফাংশনে ফিরে যান এবং সেই রেখার মূল্যায়ন চালিয়ে যান:

x = (0 + 5);

এবং, যেহেতু এর মান xইতিমধ্যে প্রতিস্থাপিত হয়েছে, এটি রয়ে গেছে 0

পরিশেষে, দোভাষা সংযোজন করে, এতে সঞ্চয় 5করে xএবং লগ করে।

আপনি কোনও অবজেক্ট প্রোপার্টি গেটার / সেটারের ভিতরে লগ ইন করে এই আচরণটি পরীক্ষা করতে পারেন (এই উদাহরণে, y.zএর মান প্রতিফলিত করে x:

let x = 0;
const y = {
  get z() {
    console.log('get x :', x);
    return x;
  },
  set z(value) {
    console.log('set x =', value);
    x = value;
  }
};

async function test() {
  console.log('inside async function');
  y.z += await 5;
  console.log('x :', x);
}

test();
console.log('main script');
y.z += 1;
console.log('x :', x);

/* Output:

inside async function
get x : 0   <-- async fn reads
main script
get x : 0
set x = 1
x : 1
set x = 5   <-- async fn writes
x : 5       <-- async fn logs

*/
/* Just to make console fill the available space */
.as-console-wrapper {
  max-height: 100% !important;
}


সম্ভবতx += yx = (x + y) লক্ষণীয় মূল্য: "আপনি সম্ভবত জানেন যে এটি অভিন্ন ।" - প্রতিটি ভাষায় প্রতিটি পরিস্থিতিতে এটি হয় না, তবে সাধারণভাবে আপনি তাদের একইরকম অভিনয় করতে পারেন।
নিক

11

আপনার বিবৃতি x += await 5desugars

const _temp = x;
await;
x = _temp + 5;

_tempOrary মান 0, এবং আপনি পরিবর্তন xকরার সময় await(যা আপনার কোড আছে) এটিকে ব্যাপার নিয়োগ পরার না, 5পরে।


9

এই কোডটি অনুসরণ করা বেশ জটিল কারণ এটি কিছু অপ্রত্যাশিত async লাফিয়ে পিছনে পিছনে লাগে। আসুন এটি পরীক্ষা করা যাক (কাছাকাছি) এটি কীভাবে কার্যকর হতে চলেছে এবং কেন পরে তা ব্যাখ্যা করব। আমি একটি সংখ্যা যুক্ত করতে কনসোল লগগুলিও পরিবর্তন করেছি - তাদের উল্লেখ সহজ করে তোলে এবং লগডটি আরও ভাল দেখায়:

let x = 0;                        // 1 declaring and assigning x

async function test() {           // 2 function declaration
    x += await 5;                 // 4/7 assigning x
    console.log('x1 :', x);       // 8 printing
}

test();                           // 3 invoking the function
x += 1;                           // 5 assigning x
console.log('x2 :', x);           // 6 printing

সুতরাং, কোডটি আসলে কোনও সরল পদ্ধতিতে চলছে না, এটি নিশ্চিতভাবে। এবং আমরা একটি অদ্ভুত আছে4/7 পাশাপাশি জিনিস রয়েছে। এবং এটি এখানেই সমস্যাটির সম্পূর্ণতা।

প্রথম সব, এর শোধন করি - ASYNC ফাংশন হয় না আসলে কঠোরভাবে asynchronious। awaitকীওয়ার্ডটি ব্যবহার করা হলে তারা কেবলমাত্র মৃত্যুদন্ড কার্যকর করে বিরতি দিতে পারে । এটি ছাড়াই, তারা শীর্ষ থেকে নীচে, সংক্ষেপে প্রকাশের পরে এক্সপ্রেশন কার্যকর করে:

async function foo() {
  console.log("--one");
  console.log("--two");
}

console.log("start");
foo();
console.log("end");

async function foo() {
  console.log("--one");
  await 0; //just satisfy await with an expression
  console.log("--two");
}

console.log("start");
foo();
console.log("end");

সুতরাং, প্রথম জিনিস আমরা জানি যে ব্যবহার করার প্রয়োজন awaitকরতে হবে বাকি ফাংশনের পরে চালানো। প্রদত্ত উদাহরণে, এর অর্থ console.log('x1 :', x)কার্যকর করা যাচ্ছে বাকী সিঙ্ক্রোনাস কোডের পরে করা হবে। এটি কারণ যে কোনও প্রতিশ্রুতি বর্তমান ইভেন্ট লুপ শেষ হওয়ার পরে সমাধান করা হবে।

সুতরাং, এটি ব্যাখ্যা করে যে আমরা কেন প্রথমেx2 : 1 লগইন হব এবং কেন দ্বিতীয় লগইন করছি তবে কেন পরবর্তী মানটি নয় । যৌক্তিকভাবে হওয়া উচিত ... তবে এখানে কীওয়ার্ডের দ্বিতীয় ধরণটি রয়েছে - এটি ফাংশনটির কার্য সম্পাদনকে বিরতি দেবে তবে ইতিমধ্যে এটি চালানোর আগে কিছু নয়। আসলে নিম্নলিখিত পদ্ধতিতে প্রক্রিয়াজাত হতে চলেছেx2 : 55x += await 55awaitx += await 5

  1. এর মানটি আনুন x। ফাঁসি কার্যকর করার সময়, এটিই ছিল 0
  2. awaitপরবর্তী প্রকাশ যা হয় 5। সুতরাং, ফাংশনটি এখন বিরতি দেয় এবং পরে এটি আবার শুরু করা হবে।
  3. ফাংশনটি আবার শুরু করুন। এক্সপ্রেশন 5 হিসাবে সমাধান করা হয়।
  4. ১ থেকে মান এবং ২/৩ থেকে প্রকাশটি: 0 + 5
  5. 4 থেকে মান নির্ধারণ করুন x

সুতরাং, এটা পরে ফাংশন পড়ল যতি পড়তে যে xহয় 0এবং যখন এটি ইতিমধ্যে পরিবর্তন হয়েছে, কিন্তু, তা না মান পুনরায় পড়তে নেই শুরু x

আমরা মোড়ক খোলা তাহলে awaitমধ্যে Promiseসমতুল্য যে চালানো হবে, আপনি আছে:

let x = 0;                        // 1 declaring and assigning x

async function test() {           // 2 function declaration
    const temp = x;               // 4 value read of x
    await 0; //fake await to pause for demo
    return new Promise((resolve) => {
      x = temp + 5;               // 7 assign to x
      console.log('x1 :', x);     // 8 printing
      resolve();
    });
}

test();                           // 3 invoking the function
x += 1;                           // 5 assigning x
console.log('x2 :', x);           // 6 printing


3

ইয়া এটির সামান্য কৌশলটি যা ঘটছে তা হ'ল উভয় সংযোজন ক্রিয়াকলাপ প্যারালাইভাবে ঘটছে যাতে অপারেশনটি এরকম হবে:

প্রতিশ্রুতির মধ্যে: x += await 5==> x = x + await 5==> x = 0 + await 5==>5

বাইরে: x += 1==> x = x + 1==> x = 0 + 1==>1

যেহেতু উপরের সমস্ত ক্রিয়াকলাপগুলি বাম থেকে ডান ঘটছে তাই সংযোজনের প্রথম অংশটি একই সাথে গণনা করা যেতে পারে এবং যেহেতু 5 এর আগে একটি প্রতীক্ষা রয়েছে যে অ্যাডিটিও কিছুটা বিলম্ব করতে পারে। কোডের মধ্যে ব্রেকপয়েন্ট স্থাপন করে আপনি কার্যকর করতে পারেন।


1

অ্যাসিঙ্ক এবং অ্যাওয়েট প্রতিশ্রুতির এক্সটেনশন। একটি অ্যাসিঙ্ক ফাংশনটিতে একটি প্রতীক্ষিত অভিব্যক্তি থাকতে পারে যা অ্যাসিঙ্ক ফাংশনটির কার্য সম্পাদনকে থামিয়ে দেয় এবং পাস হওয়া প্রতিশ্রুতির রেজোলিউশনের জন্য অপেক্ষা করে এবং তারপরে অ্যাসিঙ্ক ফাংশনটির সম্পাদন পুনরায় শুরু করে এবং সমাধান হওয়া মানটি ফেরত দেয়। মনে রাখবেন, অপেক্ষার কীওয়ার্ডটি কেবলমাত্র async ফাংশনগুলির মধ্যে বৈধ।

আপনি যদি পরীক্ষার ফাংশনটি কল করার পরেও x এর মান পরিবর্তন করে ফেলেছেন, তবুও x এর মান 0 থাকবে কারণ অ্যাসিঙ্ক ফাংশন ইতিমধ্যে এটির একটি নতুন উদাহরণ তৈরি করেছে। মানে এর পরিবর্তকের পরিবর্তে সমস্ত কিছু পরিবর্তিত হওয়ার পরে এটির कॉल করার পরে এর মানটি পরিবর্তন হবে না। আপনি যদি আপনার বর্ধিততা পরীক্ষার ফাংশনের উপরে রাখেন তবে।


" মানে এর পরিবর্তকের পরিবর্তে সমস্ত কিছু পরিবর্তিত হয় তার নাম পরিবর্তনের পরে এটি পরিবর্তিত হবে না ": এটি সত্য নয়। এসিঙ্ক ফাংশন কি তাদের সম্পাদনের সময় পরিবর্তনশীল পরিবর্তন পাবেন। কেবল এটি ব্যবহার করে দেখুন: let x="Didn't receive change"; (async()=>{await 'Nothing'; console.log(x); await new Promise(resolve=>setTimeout(resolve,2000)); console.log(x)})(); x='Received synchronous change'; setTimeout(()=>{x='Received change'},1000)এটি Received synchronous changeReceived change
আউটপুটস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.