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


660

নিম্নলিখিত উদাহরণগুলি দেওয়া, কেন 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



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

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

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

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

উত্তর:


535

এক শব্দ উত্তর: asynchronicity

Forewords

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


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

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

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

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

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

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

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

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

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

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

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

এটা সত্যিই সহজ। অ্যাসিনক্রোনাস ফাংশন নির্বাহের উপর নির্ভর করে যুক্তিটি এই অ্যাসিনক্রোনাস ফাংশনটির ভিতরে থেকেই শুরু করা / কল করা উচিত। উদাহরণস্বরূপ, 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
আপনার শেষ উদাহরণে, আপনি বেনাম ফাংশন ব্যবহার করার কোনও নির্দিষ্ট কারণ আছে বা নামযুক্ত ফাংশনগুলি ব্যবহার করে এটি একইরকম হবে?
জেডিলেজ 3'16

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

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

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

@Fabricio আমি বৈশিষ্ট সংজ্ঞা "> = 4ms বাতা" জন্য তাকিয়ে আছে, কিন্তু এটা খুঁজে পাইনি - আমি MDN তে (নেস্টেড কল clamping জন্য) অনুরূপ প্রক্রিয়া কিছু উল্লেখ পাওয়া যায় নি - developer.mozilla.org/en-US/docs / ওয়েব / এপিআই /… - কারও কি এইচটিএমএল স্পেকের ডান অংশের লিঙ্ক আছে?
সেবি

145

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


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

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

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

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

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

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


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

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

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

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

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


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

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

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

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)।


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

67

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

অ্যাসিক্রোনাস পদ্ধতিতে (এই ক্ষেত্রে 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.+++) সমর্থন করে তবে আপনি 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()কল করার বিষয়ে কী বোঝাতে চেয়েছেন । একটি নতুন প্রশ্ন পোস্ট করার জন্য সম্ভবত সেরা।
জনিএইচকে

52

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

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

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


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

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

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

13

অন্যান্য উত্তরগুলি দুর্দান্ত এবং আমি এটির জন্য সরাসরি উত্তর দিতে চাই want কেবল 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এক যে কিভাবে কাজ করে?
ইনটেক্সএক্স

10

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

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

1।

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

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

2।

2

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

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.