আমি জাভাস্ক্রিপ্টে কীভাবে একটি অ্যাসিঙ্ক্রোনাস ফাংশন তৈরি করতে পারি?


143

এই কোডটি দেখুন :

<a href="#" id="link">Link</a>
<span>Moving</span>

$('#link').click(function () {
    console.log("Enter");
    $('#link').animate({ width: 200 }, 2000, function() {
         console.log("finished");            
    });    
    console.log("Exit");    
});

আপনি কনসোলে দেখতে পাচ্ছেন যে "অ্যানিমেট" ফাংশনটি অবিচ্ছিন্ন, এবং এটি ইভেন্ট হ্যান্ডলার ব্লক কোডটির প্রবাহকে "কাঁটাচামচ" করেছে s আসলে :

$('#link').click(function () {
    console.log("Enter");
    asyncFunct();
    console.log("Exit");    
});

function asyncFunct() {
    console.log("finished");
}

ব্লক কোড প্রবাহ অনুসরণ করুন!

যদি আমি function asyncFunct() { }এই আচরণটি দিয়ে আমার তৈরি করতে চাই, তবে আমি এটি জাভাস্ক্রিপ্ট / jquery দিয়ে কীভাবে করতে পারি? আমি মনে করি ব্যবহার না করে একটি কৌশল আছে setTimeout()


jQuery উত্সগুলিতে একবার দেখুন :)
ইয়টস্কেভিচ

.Animate () গণিত একটি কলব্যাক ব্যবহার করে। অ্যানিমেটেড কলটিব্যাক কল করবে যখন অ্যানিমেশনটি সম্পূর্ণ হবে। আপনার যদি .animate () এর একই আচরণের প্রয়োজন হয় তবে যা আপনার প্রয়োজন তা একটি কলব্যাক (কিছু অন্যান্য ক্রিয়াকলাপের পরে "মূল" ফাংশন দ্বারা ডাকা হয়)। আপনার যদি "ফুল" অ্যাসিঙ্ক ফাংশন প্রয়োজন হয় (কার্যকরভাবে ফ্লো ব্লক করে ব্লুথ বলে একটি ফাংশন) need এক্ষেত্রে আপনি প্রায় 0 দেরীতে সেটটাইমআউট () ব্যবহার করতে পারেন।
ফ্যাবিও বুদা

@ ফ্যাবিও বুদা: কলব্যাক () কেন এক ধরণের অ্যাসিঙ্ক প্রয়োগ করতে হবে? আসলে, এটি jsfiddle.net/5H9XT/9 করেনি
মার্কজজ

আসলে "কলব্যাক" এর পরে আমি সেটটাইমআউট সহ একটি "পূর্ণ" অ্যাসিঙ্ক পদ্ধতিটি উদ্ধৃত করেছিলাম। আমি অন্য কোডের পরে ফাংশনটি যেভাবে কল করা হয় সেভাবে সিউডো-অ্যাসিঙ্ক হিসাবে কলব্যাক বলতে চেয়েছিলাম :-)
ফ্যাবিও বুদা

উত্তর:


185

আপনি সত্যিকারের কাস্টম অ্যাসিনক্রোনাস ফাংশন করতে পারবেন না। আপনাকে শেষ পর্যন্ত স্থানীয়ভাবে সরবরাহ করা কোনও প্রযুক্তির উপর নির্ভর করতে হবে, যেমন:

  • setInterval
  • setTimeout
  • requestAnimationFrame
  • XMLHttpRequest
  • WebSocket
  • Worker
  • কিছু HTML5 API গুলি যেমন ফাইল এপিআই, ওয়েব ডাটাবেস এপিআই
  • প্রযুক্তি যা সমর্থন করে onload
  • ... অনেকে

আসলে, অ্যানিমেশন jQuery ব্যবহারের জন্য setInterval


1
গতকাল আমি এক বন্ধুর সাথে এটি নিয়ে আলোচনা করছিলাম তাই এই উত্তরটি নিখুঁত! আমি async ফাংশনগুলি বুঝতে পারি এবং সনাক্ত করতে পারি এবং এগুলি সঠিকভাবে জেএসে ব্যবহার করতে পারি। তবে কেবল কেন আমরা কাস্টমগুলি বাস্তবায়ন করতে পারি না তা আমার কাছে পরিষ্কার নয়। এটি একটি কালো বাক্সের মতো যা আমরা জানি যে এটি কীভাবে কাজ করে (ব্যবহার করুন, বলুন setInterval) তবে এটি কীভাবে হয় তা দেখার জন্য আমরা এটি খুলতেও পারি না। আপনি কি এই বিষয়ে আরও তথ্য থাকতে চান?
ম্যাথিউস ফেলিপ

2
@ ম্যাথিউস ফিলিপ এই ফাংশনগুলি জাভাস্ক্রিপ্ট ইঞ্জিনের বাস্তবায়নের নেটিভ এবং কেবলমাত্র আপনি যে চশমার উপর নির্ভর করতে পারেন তা হ'ল এইচটিএমএল 5 টাইমার এবং ব্ল্যাক বক্স প্রকৃতির উপর নির্ভর করে যা তারা চশমা অনুসারে আচরণ করে।
Spoike

10
@ ম্যাথিউস ফিলিপ youtu.be/8aGhZQkoFbQ এই বিষয় সম্পর্কে এখন অবধি সেরা কথা ...
Andreas Niedermair

কিছু বাস্তবায়ন, বিশেষত নোড.জেএস, সমর্থনsetImmediate
জন সারেল

কী promises। এটি একটি দেয় awaitable?
নিতিন চন্দ্রন

69

আপনি একটি টাইমার ব্যবহার করতে পারেন:

setTimeout( yourFn, 0 );

( yourFnআপনার ফাংশনের একটি রেফারেন্স কোথায় )

বা, লোদাশ সহ :

_.defer( yourFn );

funcবর্তমান কল স্ট্যাকটি সাফ না হওয়া পর্যন্ত ডিফাররা অনুরোধ করছে। funcএটি চাওয়া হলে কোনও অতিরিক্ত যুক্তি সরবরাহ করা হয়।


3
এটি কাজ করে না, আমার জাভাস্ক্রিপ্ট ফাংশন যা ক্যানভাসে আঁকায় তা ইউআইকে সাড়া দেয় না।
gab06

2
@ গ্যাব06 - আমি বলব যে আপনার ক্যানভাস অঙ্কনের কাজটি তার নিজের ভাল কারণে অবরুদ্ধ হচ্ছে। এর ক্রিয়াকে অনেক ছোটতে বিভক্ত করুন এবং তাদের প্রত্যেককে একটি টাইমার দিয়ে আহ্বান করুন: আপনি দেখতে পাবেন যে এইভাবে ইন্টারফেসটি আপনার মাউস ক্লিকগুলি ইত্যাদিতে প্রতিক্রিয়া জানায়
মার্কো ফাউস্টিনেল্লি

লিঙ্কটি নষ্ট হয়ে গেছে।
জুলিয়ানসোটো

1
@ জুলিয়ানসোটো স্থির
Šime

1
setTimeoutHTML5 স্পেস দ্বারা সর্বনিম্ন সময় 4 মিলিসেকেন্ড 4 এটি 0 দেওয়ার সময় এখনও সেই সর্বনিম্ন সময় লাগবে। তবে হ্যাঁ, এটি একটি ফাংশন স্থগিতকারী হিসাবে ভাল কাজ করে।
হেজেজ

30

এখানে আপনার সহজ সমাধান রয়েছে (এটি সম্পর্কে অন্যান্য লেখার জন্য) http://www.benlesh.com/2012/05/calling- জাভাস্ক্রিপ্ট-function.html

এবং এখানে আপনার প্রস্তুত সমাধানের উপরে রয়েছে:

function async(your_function, callback) {
    setTimeout(function() {
        your_function();
        if (callback) {callback();}
    }, 0);
}

পরীক্ষা 1 ( আউটপুট '1 x 2 3' বা '1 2 x 3' বা '1 2 3 x' ):

console.log(1);
async(function() {console.log('x')}, null);
console.log(2);
console.log(3);

পরীক্ষা 2 ( সর্বদা 'x 1' আউটপুট হবে ):

async(function() {console.log('x');}, function() {console.log(1);});

এই ফাংশনটি টাইমআউট 0 দিয়ে কার্যকর করা হয় - এটি অ্যাসিনক্রোনাস টাস্ককে অনুকরণ করে


6
টেস্ট 1 আসলে কেবল কখনও '1 2 3 x' আউটপুট দিতে পারে এবং প্রতিবার '1 এক্স' আউটপুট দেওয়ার জন্য টেস্ট 2 এর গ্যারান্টিযুক্ত। টেস্ট 2-তে অপ্রত্যাশিত ফলাফলের কারণটি console.log(1)বলা হয় এবং আউটপুট ( undefined) দ্বিতীয় আর্গুমেন্ট হিসাবে পাস হয় async()। টেস্ট ১-এর ক্ষেত্রে, আমি মনে করি আপনি জাভাস্ক্রিপ্টের সম্পাদনের সারিটি পুরোপুরি বুঝতে পারেন না। যেহেতু প্রতিটি কল console.log()একই স্ট্যাকে ঘটবে, xসর্বশেষ লগ হওয়ার গ্যারান্টিযুক্ত। আমি ভুল উত্তর দেওয়ার জন্য এই উত্তরটি ভোট দিয়েছি তবে পর্যাপ্ত খ্যাতি নেই।
জোশুয়া পিকারি

1
@Joshua: এটা @fider লেখ পরীক্ষা 2 যেমন বোঝানো মনে হচ্ছে: async(function() {console.log('x')}, function(){console.log(1)});
nzn

@Nzn হ্যাঁ এবং @Joshua আমি বোঝানো TEST 2 as: async(function() {console.log('x')}, function(){console.log(1)});- আমি ইতিমধ্যে এটি সংশোধন
fider

টেস্ট 2 আউটপুটটি অ্যাসিঙ্কে 1 এক্স (ফাংশন () {সেটটাইমআউট (() => so কনসোল.লগ ('x');}, 1000)}, ফাংশন () {কনসোল.লগ (1);});
মহসেন 14

10

এখানে একটি ফাংশন যা অন্য ফাংশন নেয় এবং এমন সংস্করণ আউটপুট করে যা অ্যাসিঙ্ক চালায়।

var async = function (func) {
  return function () {
    var args = arguments;
    setTimeout(function () {
      func.apply(this, args);
    }, 0);
  };
};

এটি একটি অ্যাসিঙ্ক ফাংশনটি করার সহজ উপায় হিসাবে ব্যবহৃত হয়:

var anyncFunction = async(function (callback) {
    doSomething();
    callback();
});

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


সেটটাইমআউটটি একটি লুপে ব্যবহার করা যায় না (একই যুক্তিটি পৃথক যুক্তি দিয়ে বেশ কয়েকবার কল করুন)
ব্যবহারকারী 2284570

@ user2284570 এটি ক্লোজারগুলির জন্য। (function(a){ asyncFunction(a); })(a)
সুইভেল

1
আইআইআরসি, আপনি এটি বন্ধ না করেও অর্জন করতে পারেন:setTimeout(asyncFunction, 0, a);
সুইভেল

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

1
আমি বুঝতে পারি না কেন এই উত্তরটি upvated হয়। যখন আমি এটি আমার কোডটিতে রাখি, তখন ফাংশনটি শেষ না হওয়া পর্যন্ত প্রোগ্রামটি অবরুদ্ধ করে দেয়, যা ঠিক এটি করা উচিত নয়
মার্টিন আরজারামি

6

সম্পাদনা: আমি পুরোপুরি প্রশ্নটি ভুল বুঝেছি। ব্রাউজারে, আমি ব্যবহার করব setTimeout। যদি এটি অন্য থ্রেডে চালানো গুরুত্বপূর্ণ ছিল তবে আমি ওয়েব ওয়ার্কার্স ব্যবহার করব ।


1
? এটি একটি
অ্যাসিঙ্ক

6

দেরীতে, তবে ES6 এpromises তাদের পরিচিতির পরে ব্যবহার করে একটি সহজ সমাধান দেখানোর জন্য , এটি অ্যাসিঙ্ক্রোনাস কলগুলি অনেক সহজ পরিচালনা করে:

আপনি একটি নতুন প্রতিশ্রুতিতে অ্যাসিক্রোনাস কোড সেট করেছেন:

var asyncFunct = new Promise(function(resolve, reject) {
    $('#link').animate({ width: 200 }, 2000, function() {
        console.log("finished");                
        resolve();
    });             
});

resolve()অ্যাসিঙ্ক কল শেষ হলে সেট করার জন্য নোট ।
তারপরে আপনি অ্যাসিঙ্ক কল শেষ হয়ে যাওয়ার পরে যে কোডটি চালাতে চান তা যুক্ত .then()করুন promise প্রতিশ্রুতিটির মধ্যে:

asyncFunct.then((result) => {
    console.log("Exit");    
});

এখানে এটির একটি স্নিপেট রয়েছে:

$('#link').click(function () {
    console.log("Enter");
    var asyncFunct = new Promise(function(resolve, reject) {
        $('#link').animate({ width: 200 }, 2000, function() {
            console.log("finished");            	
            resolve();
        }); 			
    });
    asyncFunct.then((result) => {
        console.log("Exit");    
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#" id="link">Link</a>
<span>Moving</span>

বা জেএসফিডাল


6

এই পৃষ্ঠা আপনাকে একটি অ্যাসিঙ্ক জাভাস্ক্রিপ্ট ফাংশন তৈরির প্রাথমিক বিষয়গুলি সম্পর্কে জানায়।

ES2017 সাল থেকে, অ্যাসিনক্রোনাস জাভাক্রিপ্ট ফাংশনগুলি লিখতে অনেক সহজ। প্রতিশ্রুতি সম্পর্কে আপনার আরও পড়া উচিত ।


লিঙ্কটি মারা গেছে।
মার্টিন আরজারামি

3

আপনি যদি প্যারামিটারগুলি ব্যবহার করতে এবং সর্বাধিক সংখ্যক অ্যাসিঙ্ক ফাংশনগুলি নিয়ন্ত্রণ করতে চান তবে আপনি যে সাধারণ অ্যাসিঙ্ক কর্মীটি তৈরি করেছেন তা ব্যবহার করতে পারেন:

var BackgroundWorker = function(maxTasks) {
    this.maxTasks = maxTasks || 100;
    this.runningTasks = 0;
    this.taskQueue = [];
};

/* runs an async task */
BackgroundWorker.prototype.runTask = function(task, delay, params) {
    var self = this;
    if(self.runningTasks >= self.maxTasks) {
        self.taskQueue.push({ task: task, delay: delay, params: params});
    } else {
        self.runningTasks += 1;
        var runnable = function(params) {
            try {
                task(params);
            } catch(err) {
                console.log(err);
            }
            self.taskCompleted();
        }
        // this approach uses current standards:
        setTimeout(runnable, delay, params);
    }
}

BackgroundWorker.prototype.taskCompleted = function() {
    this.runningTasks -= 1;

    // are any tasks waiting in queue?
    if(this.taskQueue.length > 0) {
        // it seems so! let's run it x)
        var taskInfo = this.taskQueue.splice(0, 1)[0];
        this.runTask(taskInfo.task, taskInfo.delay, taskInfo.params);
    }
}

আপনি এটি এর মতো ব্যবহার করতে পারেন:

var myFunction = function() {
 ...
}
var myFunctionB = function() {
 ...
}
var myParams = { name: "John" };

var bgworker = new BackgroundWorker();
bgworker.runTask(myFunction, 0, myParams);
bgworker.runTask(myFunctionB, 0, null);

2
Function.prototype.applyAsync = function(params, cb){
      var function_context = this;
      setTimeout(function(){
          var val = function_context.apply(undefined, params); 
          if(cb) cb(val);
      }, 0);
}

// usage
var double = function(n){return 2*n;};
var display = function(){console.log(arguments); return undefined;};
double.applyAsync([3], display);

যদিও অন্যান্য সমাধানগুলির তুলনায় মৌলিকভাবে পৃথক নয়, আমার ধারণা আমার সমাধানটি কয়েকটি অতিরিক্ত সুন্দর জিনিসগুলি করে:

  • এটি ফাংশনগুলির পরামিতিগুলির জন্য অনুমতি দেয়
  • এটি ফাংশনটির আউটপুট কলব্যাকে পাস করে
  • এটি Function.prototypeকল করার জন্য একটি সুন্দর উপায়কে যুক্ত করার সাথে যুক্ত করা হয়েছে

এছাড়াও, বিল্ট-ইন ফাংশনের সাথে Function.prototype.applyমিলটি আমার কাছে উপযুক্ত বলে মনে হয়।


1

@ পিমভিডিবি-র দুর্দান্ত উত্তরের পাশে, এবং আপনি যেখানে ভাবছেন সেখানেই async.js প্রকৃতপক্ষে অ্যাসিনক্রোনাস ফাংশন সরবরাহ করে না। এখানে গ্রন্থাগারের মূল পদ্ধতির একটি (খুব) বাদ দেওয়া সংস্করণ দেওয়া হয়েছে:

function asyncify(func) { // signature: func(array)
    return function (array, callback) {
        var result;
        try {
            result = func.apply(this, array);
        } catch (e) {
            return callback(e);
        }
        /* code ommited in case func returns a promise */
        callback(null, result);
    };
}

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


1

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

নীচের কোডটিতে ব্যাকগ্রাউন্ডে কল করার জন্য ফাংশন রয়েছে async

Function.prototype.async = function(callback) {
    let blob = new Blob([ "self.addEventListener('message', function(e) { self.postMessage({ result: (" + this + ").apply(null, e.data) }); }, false);" ], { type: "text/javascript" });
    let worker = new Worker(window.URL.createObjectURL(blob));
    worker.addEventListener("message", function(e) {
        this(e.data.result);
    }.bind(callback), false);
    return function() {
        this.postMessage(Array.from(arguments));
    }.bind(worker);
};

এটি ব্যবহারের জন্য একটি উদাহরণ:

(function(x) {
    for (let i = 0; i < 999999999; i++) {}
        return x * 2;
}).async(function(result) {
    alert(result);
})(10);

এটি এমন একটি ফাংশন সম্পাদন করে যা forঅ্যাসিঙ্ক্রোনসিটির প্রদর্শনের জন্য সময় নেওয়ার জন্য একটি বিশাল সংখ্যার সাথে পুনরাবৃত্তি করে এবং তার পরে পাস করা সংখ্যার দ্বিগুণ হয়। asyncপদ্ধতি প্রদান করে functionযা ব্যাকগ্রাউন্ডে চেয়েছিলেন ফাংশন কল, এবং যে যা এর প্যারামিটার হিসাবে প্রদান করা হয় asynccallbacks returnএর অনন্য পরামিতি হবে। সুতরাং কলব্যাক ফাংশন আমি alertফলাফল।


0

এমডিএন এর একটি ভাল উদাহরণ রয়েছে"এটি" সংরক্ষণের সেটটাইমআউট ব্যবহারের রয়েছে।

নীচের মত:

function doSomething() {
    // use 'this' to handle the selected element here
}

$(".someSelector").each(function() {
    setTimeout(doSomething.bind(this), 0);
});
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.