আমার ক্রিয়াকলাপটি কোনও ক্রিয়াকলাপের অভ্যন্তরে পরিবর্তিত হওয়ার পরে কেন তা অপরিবর্তিত? - অ্যাসিঙ্ক্রোনাস কোড রেফারেন্স


736

নিম্নলিখিত উদাহরণগুলি দেওয়া, কেন outerScopeVarসব ক্ষেত্রেই অপরিবর্তিত?

var outerScopeVar;

var img = document.createElement('img');
img.onload = function() {
    outerScopeVar = this.width;
};
img.src = 'lolcat.png';
alert(outerScopeVar);

var outerScopeVar;
setTimeout(function() {
    outerScopeVar = 'Hello Asynchronous World!';
}, 0);
alert(outerScopeVar);

// Example using some jQuery
var outerScopeVar;
$.post('loldog', function(response) {
    outerScopeVar = response;
});
alert(outerScopeVar);

// Node.js example
var outerScopeVar;
fs.readFile('./catdog.html', function(err, data) {
    outerScopeVar = data;
});
console.log(outerScopeVar);

// with promises
var outerScopeVar;
myPromise.then(function (response) {
    outerScopeVar = response;
});
console.log(outerScopeVar);

// geolocation API
var outerScopeVar;
navigator.geolocation.getCurrentPosition(function (pos) {
    outerScopeVar = pos;
});
console.log(outerScopeVar);

কেন এটি undefinedএই সমস্ত উদাহরণে আউটপুট দেয় ? আমি কাজের দিকনির্দেশনা চাই না, আমি কেন এটি হচ্ছে তা জানতে চাই ।


দ্রষ্টব্য: এটি জাভাস্ক্রিপ্ট অ্যাসিঙ্ক্রোনসিটির জন্য একটি সাধারণ প্রশ্ন । এই প্রশ্নটি উন্নত করতে এবং আরও সরলীকৃত উদাহরণ যুক্ত করুন যা সম্প্রদায়টি সনাক্ত করতে পারে add



@ ডুকলিং ধন্যবাদ, আমি নিশ্চিত যে আমি এই লিঙ্কটি নিয়ে মন্তব্য করেছিলাম তবে স্পষ্টতই কিছু অনুপস্থিত মন্তব্য রয়েছে। এছাড়াও, আপনার সম্পাদনা সম্পর্কিত: আমি বিশ্বাস করি শিরোনামে "ক্যানোনিকাল" এবং "অ্যাসিনক্রোনিকটি" থাকার ফলে এই প্রশ্নটি অনুসন্ধান করার সময় অন্য প্রশ্নটিকে দুপ হিসাবে চিহ্নিত করার জন্য সহায়তা করা হয়। এবং অবশ্যই, এটি অ্যাসিঙ্ক্রোনসিটির ব্যাখ্যা অনুসন্ধান করার সময় গুগল থেকে এই প্রশ্নটি সন্ধান করতে সহায়তা করে।
ফ্যাব্রেসিও ম্যাট

5
"ক্যানোনিকাল অ্যাসিনক্রোনসিটির বিষয়" শিরোনামটি কিছুটা বেশি ভাবা, "অ্যাসিনক্রোনাস কোড রেফারেন্স" সহজ এবং আরও উদ্দেশ্যমূলক। আমি আরও বিশ্বাস করি যে বেশিরভাগ লোকেরা "অ্যাসিনক্রোনসিটি" এর পরিবর্তে "অ্যাসিনক্রোনাস" অনুসন্ধান করে।
ফ্যাব্রেসিও ম্যাট

2
কিছু লোক ফাংশন কল করার আগে তাদের পরিবর্তনশীল সূচনা করে। শিরোনাম যে কোনওভাবে যে প্রতিনিধিত্ব করে তা পরিবর্তন সম্পর্কে? "আমার ক্রিয়াকলাপটি কোনও ফাংশনের অভ্যন্তরে সংশোধন করার পরে কেন অবিচলিত হয়?" ?
ফেলিক্স ক্লিং

আপনি উপরে উল্লিখিত সমস্ত কোড উদাহরণে "সতর্কতা (আউটটারস্কোপবার)"; এখনই কার্যকর করে, যেখানে "আউটসোস্কোপাওয়ার" এর মান নির্ধারণের ফলে লেটার (অ্যাসিনক্রোনাসলি) হয়।
রিফ্যাক্টর

উত্তর:


580

একটি মাত্র শব্দ উত্তর: asynchronicity

Forewords

এই বিষয়টিকে স্ট্যাক ওভারফ্লোতে এখানে কমপক্ষে কয়েক হাজার বার পুনরাবৃত্তি করা হয়েছে। অতএব, প্রথমে আমি কয়েকটি অত্যন্ত দরকারী সংস্থান চিহ্নিত করতে চাই:


হাতে প্রশ্নের উত্তর

প্রথমে সাধারণ আচরণটি চিহ্নিত করা যাক। সমস্ত উদাহরণে, outerScopeVarকোনও ফাংশনের অভ্যন্তরে পরিবর্তিত হয় । এই ফাংশনটি স্পষ্টতই তাত্ক্ষণিকভাবে কার্যকর করা হয় না, এটি আর্গুমেন্ট হিসাবে অর্পণ বা পাস করা হচ্ছে। এটাই আমরা কলব্যাক বলি ।

এখন প্রশ্ন, কখন যে কলব্যাক বলা হয়?

এটি মামলার উপর নির্ভর করে। আসুন আবার কিছু সাধারণ আচরণ সন্ধান করার চেষ্টা করুন:

  • img.onloadভবিষ্যতে কোনও সময় বলা যেতে পারে , কখন (এবং যদি) চিত্রটি সফলভাবে লোড হয়েছে।
  • setTimeoutবিলম্বের মেয়াদ শেষ হওয়ার পরে এবং সময়সীমাটি বাতিল না হওয়ার পরে ভবিষ্যতে কোনও সময় ডাকা যেতে পারে clearTimeout। দ্রষ্টব্য: 0দেরি হিসাবে ব্যবহার করার পরেও , সমস্ত ব্রাউজারের ন্যূনতম সময়সীমা বিলম্ব ক্যাপ থাকে (HTML5 স্পেসে 4 মিমি হিসাবে নির্দিষ্ট)।
  • jQuery $.postএর কলব্যাক ভবিষ্যতে কখনও কখনও কল করা যেতে পারে , কখন (এবং যদি) Ajax অনুরোধটি সফলভাবে সম্পন্ন হয়েছে।
  • ফাইলটি সফলভাবে পড়া বা ত্রুটি ছুঁড়ে ফেলার সময় নোড.জেসগুলি ভবিষ্যতে কখনও কখনওfs.readFile ডাকা যেতে পারে ।

সব ক্ষেত্রেই আমাদের একটি কলব্যাক রয়েছে যা ভবিষ্যতে কোনও সময় চলতে পারে । এটি "ভবিষ্যতের কিছু সময়" এটাকে আমরা অ্যাসিক্রোনাস প্রবাহ হিসাবে উল্লেখ করি ।

অ্যাসিঙ্ক্রোনাস এক্সিকিউশনকে সিঙ্ক্রোনাস প্রবাহের বাইরে ঠেলে দেওয়া হয়। তা হল, সিঙ্ক্রোনাস কোড স্ট্যাকটি কার্যকর করার সময় অ্যাসিক্রোনাস কোড কখনই কার্যকর হবে না । এটি জাভাস্ক্রিপ্টটির একক থ্রেড হওয়া অর্থ।

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

অর্থাত, হাতে আঁকা লাল আকারগুলিতে হাইলাইট অ্যাসিক্রোনাস কোডটি তাদের নিজ নিজ কোড ব্লকগুলিতে অবশিষ্ট সমস্ত সিঙ্ক্রোনাস কোড সম্পাদন করার পরে কেবল কার্যকর করা যেতে পারে:

অ্যাসিঙ্ক কোড হাইলাইট করা

সংক্ষেপে, কলব্যাক ফাংশনগুলি সুসংগতভাবে তৈরি করা হয় তবে সংবিধানে কার্যকর করা হয়। আপনি কেবল অ্যাসিক্রোনাস ফাংশন কার্যকর করার উপর নির্ভর করতে পারবেন না যতক্ষণ না আপনি জানেন যে এটি কার্যকর হয়েছে এবং কীভাবে এটি করবেন?

এটা সত্যিই সহজ। অ্যাসিনক্রোনাস ফাংশন নির্বাহের উপর নির্ভর করে যুক্তিটি এই অ্যাসিনক্রোনাস ফাংশনটির ভিতরে থেকেই শুরু করা / কল করা উচিত। উদাহরণস্বরূপ, alertগুলি এবং চলন্তconsole.log গুলিকে কলব্যাক ফাংশনের অভ্যন্তরে প্রত্যাশিত ফলাফলকে আউটপুট দেবে, কারণ ফলাফলটি সেই সময়ে উপলব্ধ।

আপনার নিজস্ব কলব্যাক যুক্তি বাস্তবায়ন করা হচ্ছে

অ্যাসিনক্রোনাস ফাংশন থেকে প্রায়শই আপনাকে ফলাফলের সাথে আরও বেশি কিছু করতে হবে বা অ্যাসিঙ্ক্রোনাস ফাংশনটি কোথায় ডাকা হয়েছে তার উপর নির্ভর করে ফলাফলের সাথে বিভিন্ন জিনিস করা প্রয়োজন। আরও কিছু জটিল উদাহরণ মোকাবেলা করা যাক:

var outerScopeVar;
helloCatAsync();
alert(outerScopeVar);

function helloCatAsync() {
    setTimeout(function() {
        outerScopeVar = 'Nya';
    }, Math.random() * 2000);
}

নোট: আমি ব্যবহার করছি setTimeoutএকটি জেনেরিক অ্যাসিঙ্ক্রোনাস ফাংশন হিসাবে একটি র্যান্ডম বিলম্ব, একই উদাহরণ অ্যাজাক্স, প্রযোজ্য readFile, onloadএবং অন্য কোন অ্যাসিঙ্ক্রোনাস প্রবাহ।

এই উদাহরণটি অন্যান্য উদাহরণগুলির মতো একই সমস্যাটিতে স্পষ্টভাবে ভুগছে, অ্যাসিক্রোনাস ফাংশন কার্যকর না হওয়া পর্যন্ত এটি অপেক্ষা করে না।

আসুন এটি আমাদের নিজস্ব একটি কলব্যাক সিস্টেম বাস্তবায়নের সাথে মোকাবিলা করি। প্রথমে, আমরা সেই কুৎসিত থেকে মুক্তি পেয়েছি outerScopeVarযা এই ক্ষেত্রে সম্পূর্ণ অকেজো। তারপরে আমরা একটি পরামিতি যুক্ত করব যা একটি ফাংশন আর্গুমেন্ট, আমাদের কলব্যাক গ্রহণ করে। যখন অ্যাসিঙ্ক্রোনাস অপারেশন শেষ হয়, আমরা এই কলব্যাকটিকে ফলাফলটি পাস করে বলি। বাস্তবায়ন (ক্রমে মন্তব্য পড়ুন):

// 1. Call helloCatAsync passing a callback function,
//    which will be called receiving the result from the async operation
helloCatAsync(function(result) {
    // 5. Received the result from the async function,
    //    now do whatever you want with it:
    alert(result);
});

// 2. The "callback" parameter is a reference to the function which
//    was passed as argument from the helloCatAsync call
function helloCatAsync(callback) {
    // 3. Start async operation:
    setTimeout(function() {
        // 4. Finished async operation,
        //    call the callback passing the result as argument
        callback('Nya');
    }, Math.random() * 2000);
}

উপরের উদাহরণের কোড স্নিপেট:

// 1. Call helloCatAsync passing a callback function,
//    which will be called receiving the result from the async operation
console.log("1. function called...")
helloCatAsync(function(result) {
    // 5. Received the result from the async function,
    //    now do whatever you want with it:
    console.log("5. result is: ", result);
});

// 2. The "callback" parameter is a reference to the function which
//    was passed as argument from the helloCatAsync call
function helloCatAsync(callback) {
    console.log("2. callback here is the function passed as argument above...")
    // 3. Start async operation:
    setTimeout(function() {
    console.log("3. start async operation...")
    console.log("4. finished async operation, calling the callback, passing the result...")
        // 4. Finished async operation,
        //    call the callback passing the result as argument
        callback('Nya');
    }, Math.random() * 2000);
}

প্রায়শই রিয়েল ইউজ ক্ষেত্রে, ডম এপিআই এবং বেশিরভাগ লাইব্রেরি ইতিমধ্যে কলব্যাক কার্যকারিতা সরবরাহ করে ( helloCatAsyncএই প্রতিবেদনের উদাহরণটিতে প্রয়োগ)। আপনাকে কেবল কলব্যাক ফাংশনটি পাস করতে হবে এবং এটি বুঝতে হবে যে এটি সিঙ্ক্রোনাস প্রবাহের বাইরে চলে যাবে এবং এটির জন্য আপনার কোডটি পুনর্গঠন করবে।

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

returnএকটি অ্যাসিঙ্ক্রোনাস কলব্যাক থেকে কোনও মান স্থাপনের পরিবর্তে , আপনাকে কলব্যাক প্যাটার্ন ব্যবহার করতে হবে, বা ... প্রতিশ্রুতি।

অঙ্গীকার

যদিও ভ্যানিলা জেএস-এর সাথে কলব্যাককে জাহান্নামে রাখার উপায় রয়েছে , প্রতিশ্রুতিগুলি জনপ্রিয়তার সাথে বেড়ে চলেছে এবং বর্তমানে ইএস 6-তে প্রমিত হয় (দেখুন প্রতিশ্রুতি - এমডিএন )।

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


জাভাস্ক্রিপ্ট অ্যাসিঙ্ক্রোনসিটি সম্পর্কে আরও পড়ার উপাদান

  • আর্ট অফ নোড - কলব্যাকগুলি ভিনিলা জেএস উদাহরণ এবং নোড.জেএস কোড সহ অ্যাসিঙ্ক্রোনাস কোড এবং কলব্যাকগুলি খুব ভালভাবে ব্যাখ্যা করে।

দ্রষ্টব্য: আমি এই উত্তরটিকে সম্প্রদায় উইকি হিসাবে চিহ্নিত করেছি, সুতরাং কমপক্ষে 100 টি নামকরা যেকোনও এটি সম্পাদনা করে উন্নত করতে পারে! দয়া করে এই উত্তরটি উন্নত করতে দ্বিধা বোধ করুন, বা আপনিও চাইলে সম্পূর্ণ নতুন উত্তর জমা দিন।

আমি এই প্রশ্নটিকে অ্যাসাক্রোনসিটি বিষয়গুলির জবাব দিতে আধ্যাত্মিক বিষয়গুলিতে পরিণত করতে চাই যা অ্যাজাক্সের সাথে সম্পর্কিত নয় (এজন্য কীভাবে একটি এজেএক্স কল থেকে প্রতিক্রিয়া ফিরিয়ে আনা যায়? তার জন্য) এই বিষয়টিকে আপনার যথাসম্ভব ভাল এবং সহায়ক হতে সহায়তা প্রয়োজন !


1
আপনার শেষ উদাহরণে, আপনি বেনাম ফাংশন ব্যবহার করার কোনও নির্দিষ্ট কারণ আছে বা নামযুক্ত ফাংশনগুলি ব্যবহার করে এটি একইরকম হবে?
জেডিলেজ

1
কোড উদাহরণগুলি কিছুটা অদ্ভুত কারণ আপনি কল করার পরে এটি ফাংশনটি ঘোষণা করছেন। অবশ্যই উত্তোলনের কারণে কাজ করে, তবে এটি উদ্দেশ্যমূলক ছিল?
বার্গি

2
এটা কি অচলাবস্থা ফেলিক্স ক্লিংং আপনার উত্তরের দিকে ইঙ্গিত করছে এবং আপনি ফেলিক্স উত্তরের দিকে ইঙ্গিত করছেন
মাহি

1
আপনার বুঝতে হবে যে রেড সার্কেল কোডটি কেবলমাত্র অ্যাসিঙ্ক কারণ এটি NATIVE async জাভাস্ক্রিপ্ট ফাংশন দ্বারা কার্যকর করা হচ্ছে। এটি আপনার জাভাস্ক্রিপ্ট ইঞ্জিনের একটি বৈশিষ্ট্য - তা নোড.জেএস বা ব্রাউজারই হোক। এটি async কারণ এটি একটি ফাংশনে "কলব্যাক" হিসাবে প্রেরণ করা হচ্ছে যা মূলত একটি কালো বাক্স (সি ইত্যাদিতে প্রয়োগ করা হয়)। অসহায় বিকাশকারীদের কাছে তারা অ্যাসিঙ্ক ... কেবল কারণ। আপনি যদি নিজের অ্যাসিঙ্ক ফাংশনটি লিখতে চান তবে সেটটিটাইমআউট (মাইফাঙ্ক, 0) এ প্রেরণ করে আপনাকে এটি হ্যাক করতে হবে। আপনি কি এটা করা উচিত? অন্য বিতর্ক .... সম্ভবত না।
শান অ্যান্ডারসন

@ ফ্যাব্রিকিও আমি "> = 4 এসএমএস ক্ল্যাম্প" সংজ্ঞায়িত বিশ্লেষণের সন্ধান করেছি, কিন্তু এটি খুঁজে পেলাম না - এমডিএন-তে অনুরূপ প্রক্রিয়াটির (নেস্টেড কলস ক্ল্যাম্পিংয়ের জন্য) কিছু উল্লেখ পেয়েছি - বিকাশকারী.মোজিলা.আর.ইন- ইউএস / ডকস / ওয়েব / এপিআই /… - কারও কি এইচটিএমএল স্পেকের ডান অংশের লিঙ্ক আছে?
সেবি

156

Fabrício এর উত্তর স্পট হয়; তবে আমি তার উত্তরটি কম প্রযুক্তিগত কিছু দিয়ে পরিপূরক করতে চেয়েছিলাম, যা অ্যাসিঙ্ক্রোনসিটির ধারণাটি ব্যাখ্যা করতে সহায়তা করার জন্য সাদৃশ্যটির উপর দৃষ্টি নিবদ্ধ করে


একটি সাদৃশ্য ...

গতকাল, আমি যে কাজটি করছিলাম তার জন্য সহকর্মীর কিছু তথ্য দরকার ছিল required আমি তাকে বেঁধে রেখেছি; কথোপকথনটি কীভাবে চলেছিল তা এখানে:

আমার : হাই বব, আমি জানি কিভাবে আমরা প্রয়োজন foo বিন্যাস 'd বার ' গত সপ্তাহে ঘ। জিম এটির জন্য একটি প্রতিবেদন চায়, এবং আপনি কেবল তারাই এই সম্পর্কে বিশদ জানেন।

বব : অবশ্যই, তবে আমার প্রায় 30 মিনিট লাগবে?

আমাকে : দারুণ বব। আপনি তথ্য পেলে আমাকে আবার একটি রিং দিন!

এই মুহুর্তে, আমি ফোনটি হ্যাং করলাম। যেহেতু আমার প্রতিবেদনটি সম্পূর্ণ করার জন্য আমার কাছে ববয়ের তথ্যের প্রয়োজন ছিল, তাই আমি এই প্রতিবেদনটি ছেড়ে দিয়েছিলাম এবং পরিবর্তে একটি কফির জন্য গিয়েছিলাম, তারপরে আমি কিছু ইমেল পেয়েছিলাম। 40 মিনিট পরে (বব ধীর গতিতে), বব আবার ফোন করেছিল এবং আমাকে প্রয়োজনীয় তথ্য দিয়েছিল। এই মুহুর্তে, আমি আমার রিপোর্ট দিয়ে আমার কাজটি আবার শুরু করেছি, কারণ আমার প্রয়োজনীয় সমস্ত তথ্য ছিল।


পরিবর্তে কথোপকথনটি যদি এভাবে চলে যায়;

আমার : হাই বব, আমি জানি কিভাবে আমরা প্রয়োজন foo বিন্যাস 'd বার ' গত সপ্তাহে ঘ। জিম এটি সম্পর্কে একটি প্রতিবেদন চান, এবং আপনি কেবল তারাই এই সম্পর্কে বিশদ জানেন।

বব : অবশ্যই, তবে আমার প্রায় 30 মিনিট লাগবে?

আমাকে : দারুণ বব। আমি অপেক্ষা করব.

এবং আমি সেখানে বসে অপেক্ষা করছিলাম। আর অপেক্ষা করলাম। আর অপেক্ষা করলাম। 40 মিনিটের জন্য। অপেক্ষা ছাড়া কিছুই করছেন না। অবশেষে, বব আমাকে তথ্য দিয়েছিল, আমরা স্তব্ধ হয়ে গেলাম এবং আমি আমার প্রতিবেদনটি শেষ করলাম। তবে আমি 40 মিনিটের উত্পাদনশীলতা হারাতে চাই।


এটি অ্যাসিক্রোনাস বনাম সিঙ্ক্রোনাস আচরণ

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

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

var outerScopeVar;    
var img = document.createElement('img');

// Here we register the callback function.
img.onload = function() {
    // Code within this function will be executed once the image has loaded.
    outerScopeVar = this.width;
};

// But, while the image is loading, JavaScript continues executing, and
// processes the following lines of JavaScript.
img.src = 'lolcat.png';
alert(outerScopeVar);

উপরের কোডে আমরা জাভাস্ক্রিপ্টটি লোড করতে বলছিlolcat.png , এটি একটি স্লুও অপারেশন। এই ধীর অপারেশনটি হয়ে গেলে কলব্যাক ফাংশনটি কার্যকর করা হবে, তবে এর মধ্যে, জাভাস্ক্রিপ্ট কোডটির পরবর্তী লাইনের প্রক্রিয়া চালিয়ে যাবে; অর্থাত alert(outerScopeVar)

এই কারণেই আমরা সতর্কতা দেখছি undefined; যেহেতু alert()চিত্রটি লোড হওয়ার পরে তাত্ক্ষণিকভাবে প্রক্রিয়া করা হবে।

আমাদের কোড ফিক্স, সব আমরা যা করতে হবে সরাতে হয় alert(outerScopeVar)কোড মধ্যে কলব্যাক ফাংশন। এর ফলস্বরূপ, আমাদের আর outerScopeVarবিশ্বব্যাপী ভেরিয়েবল হিসাবে ঘোষিত চলকের দরকার নেই ।

var img = document.createElement('img');

img.onload = function() {
    var localScopeVar = this.width;
    alert(localScopeVar);
};

img.src = 'lolcat.png';

আপনি সবসময় পাবেন দেখতে কলব্যাকটি একটি ফাংশন হিসাবে নির্দিষ্ট করা হয়েছে, কারণ জাভাস্ক্রিপ্টের একমাত্র * উপায় কিছু কোড সংজ্ঞায়িত করার, তবে এটি পরবর্তীকালে চালানো নয়।

অতএব, আমাদের সমস্ত উদাহরণে function() { /* Do something */ }কলব্যাক; সমস্ত উদাহরণ ঠিক করার জন্য , আমাদের যা করতে হবে তা হল কোডটি সরানো যা সেখানে অপারেশনের প্রতিক্রিয়া প্রয়োজন!

* প্রযুক্তিগতভাবে আপনি এটিও ব্যবহার করতে পারেন eval()তবে eval()এটি এই উদ্দেশ্যে মন্দ


আমি আমার কলারকে কীভাবে অপেক্ষা করব?

আপনার কাছে বর্তমানে এর মতো কিছু কোড থাকতে পারে;

function getWidthOfImage(src) {
    var outerScopeVar;

    var img = document.createElement('img');
    img.onload = function() {
        outerScopeVar = this.width;
    };
    img.src = src;
    return outerScopeVar;
}

var width = getWidthOfImage('lolcat.png');
alert(width);

যাইহোক, আমরা এখন জানি যে return outerScopeVarঅবিলম্বে ঘটে যায়; onloadকলব্যাক ফাংশন পরিবর্তনশীল আপডেট করার আগে । এটি getWidthOfImage()প্রত্যাবর্তন undefinedএবং undefinedসতর্ক হওয়ার দিকে পরিচালিত করে ।

এটি ঠিক করতে, আমাদের ফাংশন কলিংয়ের অনুমতি দেওয়া দরকার getWidthOfImage() একটি কলব্যাক নিবন্ধন , তারপরে প্রস্থের সতর্কতাটিকে সেই কলব্যাকের মধ্যে স্থানান্তরিত করতে হবে;

function getWidthOfImage(src, cb) {     
    var img = document.createElement('img');
    img.onload = function() {
        cb(this.width);
    };
    img.src = src;
}

getWidthOfImage('lolcat.png', function (width) {
    alert(width);
});

... আগের মত, নোট করুন যে আমরা বিশ্বব্যাপী ভেরিয়েবলগুলি মুছে ফেলতে সক্ষম হয়েছি (এই ক্ষেত্রে width)।


4
তবে কীভাবে সতর্কতা বা কনসোলকে প্রেরণে দরকারী যদি আপনি ফলাফলগুলি অন্য গণনায় ব্যবহার করতে চান বা কোনও বস্তু ভেরিয়েবলে সঞ্চয় করতে চান?
কেন

73

এখানে এমন লোকদের জন্য আরও সংক্ষিপ্ত উত্তর দেওয়া হচ্ছে যা দ্রুত রেফারেন্স খুঁজছেন পাশাপাশি প্রতিশ্রুতি এবং অ্যাসিঙ্ক / প্রতীক্ষা ব্যবহার করে কিছু উদাহরণ সন্ধান করছেন।

অ্যাসিক্রোনাস পদ্ধতিতে (এই ক্ষেত্রে setTimeout) কল করে কোনও বার্তা দেয় এমন ফাংশনের জন্য নিখুঁত পদ্ধতির (যা কাজ করে না) দিয়ে শুরু করুন:

function getMessage() {
  var outerScopeVar;
  setTimeout(function() {
    outerScopeVar = 'Hello asynchronous world!';
  }, 0);
  return outerScopeVar;
}
console.log(getMessage());

undefined এই ক্ষেত্রে লগ ইন কারণ getMessage হয়ে যায়setTimeout কলব্যাক কল করার আগে ফেরত আসে এবং আপডেট হয় outerScopeVar

এটি সমাধানের দুটি প্রধান উপায় ব্যবহার করা হচ্ছে হ'ল কলব্যাক এবং প্রতিশ্রুতি :

Callbacks

এখানে পরিবর্তনটি হ'ল এমন getMessageএকটি callbackপ্যারামিটার গ্রহণ করে যা একবার উপলব্ধ হয়ে গেলে ফলাফলগুলি কলিং কোডে ফিরিয়ে দেওয়ার জন্য ডাকা হবে।

function getMessage(callback) {
  setTimeout(function() {
    callback('Hello asynchronous world!');
  }, 0);
}
getMessage(function(message) {
  console.log(message);
});

অঙ্গীকার

প্রতিশ্রুতিগুলি এমন একটি বিকল্প সরবরাহ করে যা কলব্যাকগুলির চেয়ে আরও নমনীয় কারণ তারা একাধিক অ্যাসিঙ্ক ক্রিয়াকলাপ সমন্বয় করতে প্রাকৃতিকভাবে একত্রিত হতে পারে। একটি অঙ্গীকার / এ + + মান বাস্তবায়ন নেটিভ Node.js (0.12+) এবং অনেক বর্তমান ব্রাউজার সরবরাহ করা হয়, কিন্তু মত লাইব্রেরি বাস্তবায়িত হয় Bluebird এবং প্রশ্ন

function getMessage() {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve('Hello asynchronous world!');
    }, 0);
  });
}

getMessage().then(function(message) {
  console.log(message);  
});

jQuery ডিফার্ডস

jQuery কার্যকারিতা প্রদান করে যা এর ডিফার্ডগুলির সাথে প্রতিশ্রুতির অনুরূপ।

function getMessage() {
  var deferred = $.Deferred();
  setTimeout(function() {
    deferred.resolve('Hello asynchronous world!');
  }, 0);
  return deferred.promise();
}

getMessage().done(function(message) {
  console.log(message);  
});

ASYNC / অপেক্ষায় রয়েছেন

যদি আপনার জাভাস্ক্রিপ্ট এনভায়রনমেন্টের জন্য asyncএবং await(যেমন নোড.জেএস .6. includes++) সমর্থন করে তবে আপনি asyncফাংশনগুলির মধ্যে সিঙ্ক্রোনলি প্রতিশ্রুতি ব্যবহার করতে পারেন :

function getMessage () {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve('Hello asynchronous world!');
        }, 0);
    });
}

async function main() {
    let message = await getMessage();
    console.log(message);
}

main();

প্রতিশ্রুতিগুলিতে আপনার নমুনাটি হ'ল আমি গত কয়েক ঘন্টা ধরে অনুসন্ধান করছি। আপনার উদাহরণটি সুন্দর এবং একই সাথে প্রতিশ্রুতিগুলি ব্যাখ্যা করে। এটি অন্য কোথাও কেন বকবক করছে না।
ভিনসেন্ট পি

এটি সব ঠিক আছে, তবে যদি প্যারামিটারগুলির সাথে আপনার getMessage () কল করতে চান? আপনি কীভাবে উপরের লিখিত পরিস্থিতিতে?
চিওদা

2
@Chiwda আপনি শুধু গত প্যারামিটার কলব্যাক করা: function getMessage(param1, param2, callback) {...}
জনিএইচকে

আমি আপনার async/awaitনমুনা চেষ্টা করছি , কিন্তু আমি সমস্যায় পড়ছি। এটিকে তাত্ক্ষণিক না করে new Promise, আমি .Get()কল করছি এবং তাই কোনও resolve()পদ্ধতিতে অ্যাক্সেস নেই । এইভাবে আমি getMessage()প্রতিশ্রুতি ফিরিয়ে দিচ্ছি ফলাফলটি নয়। এর জন্য একটি কার্যকারী বাক্য গঠন দেখানোর জন্য আপনি নিজের উত্তরটি কিছুটা সম্পাদনা করতে পারেন?
ইন্টএক্সএক্স

@ ইনটেক্সএক্স আমি নিশ্চিত না যে আপনি .Get()কল করার বিষয়ে কী বোঝাতে চেয়েছেন । একটি নতুন প্রশ্ন পোস্ট করার জন্য সম্ভবত সেরা।
জনিএইচকে

56

সুস্পষ্টভাবে বলতে, কাপটি উপস্থাপন করে outerScopeVar

অ্যাসিঙ্ক্রোনাস ফাংশনগুলি এর মতো ...

অ্যাসিক্রোনাস কফির জন্য কল


14
যখন অ্যাসিক্রোনাস ফাংশন আইনটি সিঙ্ক্রোনসিভ করার চেষ্টা করা হচ্ছে তখন 1 সেকেন্ডে কফি পান করার চেষ্টা করা হবে এবং এটি 1 মিনিটে আপনার কোলে pouredেলে দেওয়া হবে।
তেপীম্মে

যদি এটি সুস্পষ্টভাবে বলছিল, তবে আমি মনে করি না যে প্রশ্নটি করা হয়েছিল, না?
ব্রোকলি 2000

2
@ ব্রোকলি ২000 এর অর্থ এই নয় যে আমার কাছে প্রশ্নটি সুস্পষ্ট ছিল না, তবে কাপটি অঙ্কনটিতে কী প্রতিনিধিত্ব করেছে তা স্পষ্টই নয় :)
জোহানেস ফারেনক্রুগ

14

অন্যান্য উত্তরগুলি দুর্দান্ত এবং আমি এটির জন্য সরাসরি উত্তর দিতে চাই। কেবল jQuery অ্যাসিঙ্ক্রোনাস কলগুলিতে সীমাবদ্ধ

সকল Ajax কল (তত্সহ $.getবা $.postবা $.ajax) অ্যাসিঙ্ক্রোনাস হয়।

আপনার উদাহরণ বিবেচনা

var outerScopeVar;  //line 1
$.post('loldog', function(response) {  //line 2
    outerScopeVar = response;
});
alert(outerScopeVar);  //line 3

কোড এক্সিকিউশনটি লাইন 1 থেকে শুরু হয়, ভেরিয়েবল ঘোষণা করে এবং লাইন 2, (অর্থাত্, পোস্ট অনুরোধ) এ অ্যাসিক্রোনাস কল এবং এটি কার্য সম্পাদন সম্পন্ন করার জন্য পোস্টের অনুরোধের অপেক্ষা না করে, লাইন 3 থেকে এটি কার্যকর করে।

বলুন যে পোস্টের অনুরোধটি পূর্ণ হতে 10 সেকেন্ড সময় নেয় outerScopeVar কেবল সেই 10 সেকেন্ড পরে সেট করা হবে।

চেষ্টা করে,

var outerScopeVar; //line 1
$.post('loldog', function(response) {  //line 2, takes 10 seconds to complete
    outerScopeVar = response;
});
alert("Lets wait for some time here! Waiting is fun");  //line 3
alert(outerScopeVar);  //line 4

এখন আপনি যখন এটি কার্যকর করেন, আপনি লাইন 3 এ একটি সতর্কতা পাবেন Now তারপরে আপনি যখন সতর্কতা বাক্সে ওকে ক্লিক করেন, পরবর্তী সতর্কতা প্রত্যাশিত মানটি মুদ্রণ করে, কারণ আপনি এটির জন্য অপেক্ষা করেছিলেন।

বাস্তব জীবনের দৃশ্যে কোডটি হয়ে যায়,

var outerScopeVar;
$.post('loldog', function(response) {
    outerScopeVar = response;
    alert(outerScopeVar);
});

সমস্ত কোড যা অ্যাসিঙ্ক্রোনাস কলগুলির উপর নির্ভর করে, অ্যাসিক্রোনাস ব্লকের অভ্যন্তরে সরানো হয় বা অ্যাসিঙ্ক্রোনাস কলগুলির জন্য অপেক্ষা করে।


or by waiting on the asynchronous callsএক যে কিভাবে কাজ করে?
ইন্টএক্সএক্স

@ ইনটেক্সএক্স কলব্যাক পদ্ধতি ব্যবহার করে
তেজা

আপনার কাছে কি কোনও দ্রুত সিনট্যাক্স উদাহরণ রয়েছে?
ইন্টএক্সএক্স

11

এই সমস্ত পরিস্থিতিতে outerScopeVarসংশোধন করা হয় বা একটি মূল্য নির্ধারিত হয় অবিচ্ছিন্নভাবে বা পরবর্তী সময়ে ঘটে যাওয়া (কিছু ঘটনার জন্য অপেক্ষা করা বা শোনার জন্য), যার জন্য বর্তমান কার্যকর হওয়া অপেক্ষা করবে না these এই সমস্ত ক্ষেত্রেই বর্তমান সম্পাদনা প্রবাহের ফলাফল হয়outerScopeVar = undefined

আসুন প্রতিটি উদাহরণ নিয়ে আলোচনা করুন (আমি সেই অংশটি চিহ্নিত করেছি যা অ্যাসিনক্রোনাস বলা হয় বা কিছু ঘটনা ঘটতে দেরি হয়):

1।

এখানে চিত্র বর্ণনা লিখুন

এখানে আমরা একটি eventlistner যা image.Then যে বিশেষ event.Here লোড বর্তমান সঞ্চালনের পরবর্তী লাইনের একটানা উপর মৃত্যুদন্ড কার্যকর করা হবে রেজিস্টার করো img.src = 'lolcat.png';এবং alert(outerScopeVar);এদিকে ঘটনা প্রতিফলিত নাও হতে পারে। অর্থাত্ ফান্টimg.onload লোড হওয়ার জন্য উল্লিখিত চিত্রটির জন্য অপেক্ষা করুন wait এটি ঘটবে সমস্ত উদাহরণস্বরূপ - ইভেন্টটি পৃথক হতে পারে।

2।

2

এখানে টাইমআউট ইভেন্টটি ভূমিকা পালন করে যা নির্দিষ্ট সময়ের পরে হ্যান্ডলারটিকে অনুরোধ করবে। এটি এখানে 0, তবে এখনও এটি একটি অ্যাসিনক্রোনাস ইভেন্ট নিবন্ধ করে এটি Event Queueকার্যকর করার জন্য মৃত্যুর শেষ অবস্থানে যুক্ত হবে , যা গ্যারান্টিযুক্ত বিলম্ব করে।

3।

এখানে চিত্র বর্ণনা লিখুন এবার অ্যাজাক্স কলব্যাক।

4।

এখানে চিত্র বর্ণনা লিখুন

নোডকে অ্যাসিনক্রোনাস কোডিংয়ের রাজা হিসাবে বিবেচনা করা যেতে পারে e এখানে চিহ্নিত ফাংশনটি কলব্যাক হ্যান্ডলার হিসাবে নিবন্ধিত রয়েছে যা নির্দিষ্ট ফাইলটি পড়ার পরে কার্যকর করা হবে।

5।

এখানে চিত্র বর্ণনা লিখুন

সুস্পষ্ট প্রতিশ্রুতি (ভবিষ্যতে কিছু করা হবে) অ্যাসিনক্রোনাস। জাভাস্ক্রিপ্টে স্থগিত, প্রতিশ্রুতি এবং ভবিষ্যতের মধ্যে পার্থক্যগুলি দেখুন ?

https://www.quora.com/Whats-the-difference-between-a-promise-and-a-callback-in-Javascript

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