সেটটাইমআউট (fn, 0) কখনও কখনও দরকারী কেন?


872

আমি সম্প্রতি একটি বরং বাজে বাগে চলেছি, যেখানে কোডটি <select>জাভাস্ক্রিপ্টের মাধ্যমে একটি গতিশীলভাবে লোড করছিল । এই গতিশীল লোড <select>একটি প্রাক নির্বাচিত মান ছিল। IE6, আমরা ইতিমধ্যেই নির্বাচিত ফিক্স কোড ছিল <option>, কারণ কখনও কখনও <select>এর selectedIndexমান নির্বাচিত সাথে সিঙ্কের বাইরে হবে <option>s 'এর indexনিচে যেমন অ্যাট্রিবিউট:

field.selectedIndex = element.index;

তবে এই কোডটি কাজ করছে না। যদিও ক্ষেত্রটি selectedIndexসঠিকভাবে সেট করা হচ্ছে, ভুল সূচকটি নির্বাচিত হয়ে শেষ হবে। তবে, আমি যদি alert()সঠিক সময়ে একটি বিবৃতি আটকে থাকি তবে সঠিক বিকল্পটি নির্বাচন করা হবে। এটি কোনও এক সময়কালীন সমস্যা হতে পারে ভেবে আমি এলোমেলো কিছু চেষ্টা করেছি যা আমি কোডটিতে আগে দেখেছি:

var wrapFn = (function() {
    var myField = field;
    var myElement = element;

    return function() {
        myField.selectedIndex = myElement.index;
    }
})();
setTimeout(wrapFn, 0);

এবং এই কাজ!

আমি আমার সমস্যার সমাধান পেয়েছি, তবে আমি অস্বস্তি বোধ করছি কেন এটি আমার সমস্যা ঠিক করে দেয় তা ঠিক জানি না। কারও কি অফিসিয়াল ব্যাখ্যা আছে? "পরে" ব্যবহার করে আমার ফাংশনটি কল করে আমি কোন ব্রাউজার সমস্যাটি এড়াচ্ছি setTimeout()?


2
বেশিরভাগ প্রশ্নই কেন এটি কার্যকর তা বর্ণনা করে। কেন এটি ঘটে তা আপনার যদি জানতে প্রয়োজন - আমার উত্তরটি পড়ুন: stackoverflow.com/a/23747597/1090562
সালভাদোর ডালি

18
ফিলিপ রবার্টস তাঁর আলোচনায় এখানে এটি সর্বোত্তমতম পদ্ধতিতে ব্যাখ্যা করেছেন "ইভেন্টটি কী লুপ হয়?" youtube.com/watch?v=8aGhZQkoFbQ
ভাসা

আপনি যদি তাড়াহুড়ো করে থাকেন তবে এই ভিডিওর অংশটি তিনি ঠিক প্রশ্নটি সম্বোধন করতে শুরু করেছেন: youtu.be/8aGhZQkoFbQ?t=14m54s । পুনর্গঠনহীন, পুরো ভিডিওটি অবশ্যই দেখার জন্য একটি মূল্যবান।
উইলিয়াম হ্যাম্পশায়ার

4
setTimeout(fn)setTimeout(fn, 0)বিটিডব্লিউর মতোই ।
vsync

উত্তর:


827

প্রশ্নে, এর মধ্যে একটি দৌড়ের শর্ত বিদ্যমান ছিল :

  1. ড্রপ-ডাউন তালিকাটি শুরু করার ব্রাউজারের প্রচেষ্টা, এর নির্বাচিত সূচি আপডেট করার জন্য প্রস্তুত এবং and
  2. নির্বাচিত সূচক সেট করার জন্য আপনার কোড

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

এই দৌড়টির অস্তিত্ব ছিল কারণ জাভাস্ক্রিপ্টে সম্পাদনের একক থ্রেড রয়েছে যা পৃষ্ঠা রেন্ডারিংয়ের সাথে ভাগ করা হয়েছে। ফলস্বরূপ, জাভাস্ক্রিপ্ট চলমান DOM আপডেট করা অবরুদ্ধ করে।

আপনার কাজটি ছিল:

setTimeout(callback, 0)

Invoking setTimeoutএকটি কলব্যাক, এবং শূন্য দ্বিতীয় যুক্তি কলব্যাক নির্দিষ্ট সময় নির্ধারণের হবে রেখে চালাতে হবে করা অ্যাসিঙ্ক্রোনাস , সম্ভাব্য স্বল্পতম বিলম্বের পর - যখন ট্যাব ফোকাস এবং মৃত্যুদণ্ড জাভাস্ক্রিপ্ট থ্রেড ব্যস্ত না যা 10ms কাছাকাছি হতে হবে।

ওপির সমাধানটি, তাই নির্বাচিত সূচকের সেটিংটি প্রায় 10 মিমি দেরি করে। এটি ব্রাউজারটিকে বাগ ঠিক করে ডিওএম শুরু করার সুযোগ দিয়েছে।

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


ফিলিপ রবার্টস আলাপ দেখুন "হ্যাকটি কী ইভেন্ট লুপ?" আরও বিশদ ব্যাখ্যার জন্য।


276
'সমাধানটি হ'ল জাভা স্ক্রিপ্ট কার্যকরকরণ "বিরতি" রেন্ডারিং থ্রেডগুলি ধরা দেয় catch' পুরোপুরি সত্য নয়, সেটটাইমআউট যা করে তা ব্রাউজার ইভেন্টের কাতারে একটি নতুন ইভেন্ট যুক্ত করে এবং রেন্ডারিং ইঞ্জিনটি ইতিমধ্যে সেই কাতারে থাকে (পুরোপুরি সত্য নয়, তবে যথেষ্ট ঘনিষ্ঠ হয়) তাই সেটটাইমআউট ইভেন্টের পূর্বে এটি কার্যকর করা হবে।
ডেভিড মুলদার

48
হ্যাঁ, এটি অনেক বিস্তারিত এবং আরও সঠিক উত্তর correct তবে লোকটি বুঝতে চেষ্টা করে কেন কৌশলটি কাজ করে।
স্ট্যাটিক্সন

2
@ ডেভিড মুল্ডার, এর অর্থ জাভাস্ক্রিপ্ট এক্সিকিউশন থ্রেড থেকে ব্রাউজারের পার্স সিএসএস এবং আলাদা থ্রেডে রেন্ডারিং করা?
জেসন

8
না, তারা একই থ্রেডে নীতিগতভাবে পার্স করা হয়েছে অন্যথায় DOM ম্যানিপুলেশনের কয়েকটি লাইন সমস্ত সময় রিফ্লোগুলি ট্রিগার করবে যা মৃত্যুদন্ডের গতিতে অত্যন্ত খারাপ প্রভাব ফেলবে।
ডেভিড মুলদার

30
এই ভিডিওটি আমাদের কেন সময়সীমা 0 2014.jsconf.eu/speakers/…
ডাবিবিক

665

মুখবন্ধ:

অন্যান্য উত্তরগুলির মধ্যে কিছু সঠিক তবে সমস্যাটি কী কী সমাধান হচ্ছে তা প্রকৃতপক্ষে চিত্রিত করবেন না, তাই আমি এই উত্তরটি তৈরি করেছি সেই বিশদ চিত্রণ উপস্থাপনের জন্য।

এই হিসাবে, আমি ব্রাউজারটি কী করে এবং কীভাবে ব্যবহার setTimeout()করে সহায়তা করে তার বিশদ ওয়াক- থ্রো পোস্ট করছি । এটি দীর্ঘায়িত দেখাচ্ছে তবে এটি আসলে খুব সাধারণ এবং সোজা। আমি কেবল এটি খুব বিশদভাবে তৈরি করেছি।

আপডেট: আমি একটি JSFiddle করেছেন নিচে ব্যাখ্যা লাইভ-প্রদর্শন http://jsfiddle.net/C2YBE/31/ । @ থাংচুংকে এটি কিকস্টার্ট করতে সহায়তা করার জন্য অনেক ধন্যবাদ

আপডেট 2 : ঠিক জেএসফিডাল ওয়েবসাইটটি মারা গেলে বা কোড মুছে ফেলার ক্ষেত্রে, আমি এই উত্তরটিতে খুব শেষে কোডটি যুক্ত করেছি।


বিশদ বিবরণ :

"কিছু করুন" বোতাম এবং ফলাফল ডিভের সাথে একটি ওয়েব অ্যাপ্লিকেশনটি কল্পনা করুন।

onClick"কিছু" বোতামে জন্য হ্যান্ডলার একটি ফাংশন কল "LongCalc ()", যা 2 জিনিস আছে:

  1. খুব দীর্ঘ গণনা করা হয় (বলুন 3 মিনিট সময় লাগে)

  2. ফলাফল ডিভের মধ্যে গণনার ফলাফল মুদ্রণ করে।

এখন, আপনার ব্যবহারকারীরা এটি পরীক্ষা করে শুরু করুন, "কিছু করুন" বোতামটি ক্লিক করুন এবং পৃষ্ঠাটি সেখানে 3 মিনিটের জন্য আপাতদৃষ্টিতে কিছুই করছে না, তারা অস্থির হয়ে যায়, আবার বোতামটি ক্লিক করুন, 1 মিনিট অপেক্ষা করুন, কিছুই ঘটেনি, আবার বোতামটি ক্লিক করুন ...

সমস্যাটি সুস্পষ্ট - আপনি একটি "স্ট্যাটাস" ডিআইভি চান, যা কী ঘটছে তা দেখায়। আসুন দেখুন কিভাবে এটি কাজ করে।


সুতরাং আপনি একটি "স্থিতি" ডিআইভি যুক্ত করুন (প্রাথমিকভাবে খালি), এবং 4 টি onclickকাজ করার জন্য হ্যান্ডলারটি (ফাংশন LongCalc()) সংশোধন করুন :

  1. "গণনা করা হচ্ছে ... স্থিতিটি ডিআইভিতে minutes 3 মিনিট সময় নিতে পারে" পপুলেশন করুন

  2. খুব দীর্ঘ গণনা করা হয় (বলুন 3 মিনিট সময় লাগে)

  3. ফলাফল ডিভের মধ্যে গণনার ফলাফল মুদ্রণ করে।

  4. "গণনা সম্পন্ন" স্থিতি ডিআইভিতে স্থির করুন

এবং, আপনি ব্যবহারকারীদের পুনরায় পরীক্ষার জন্য আনন্দের সাথে অ্যাপটি দিন।

তারা খুব রাগ করে আপনার দিকে ফিরে আসে। এবং ব্যাখ্যা করুন যে তারা বোতামটি ক্লিক করলে, স্ট্যাটাস ডিআইভি কখনই "গণনা করা হচ্ছে ..." স্থিতি দিয়ে আপডেট হয় না !!!


আপনি আপনার মাথা আঁচড়ান, স্ট্যাকওভারফ্লো সম্পর্কে জিজ্ঞাসা করুন (বা ডক্স বা গুগল পড়ুন) এবং সমস্যাটি উপলব্ধি করুন:

ব্রাউজার তার সমস্ত "TODO" টাস্ক (উভয় UI টাস্ক এবং জাভাস্ক্রিপ্ট কমান্ড) ইভেন্টগুলি থেকে একক সারিতে পরিণত করে । এবং দুর্ভাগ্যক্রমে, নতুন "গণনা ..." মান দিয়ে "স্থিতি" ডিআইভি পুনরায় অঙ্কন করা একটি পৃথক টোডো যা সারির শেষ দিকে যায়!

আপনার ব্যবহারকারীর পরীক্ষার সময় ইভেন্টগুলির একটি বিচ্ছেদ, প্রতিটি ইভেন্টের পরে সারির সামগ্রীগুলি এখানে রয়েছে:

  • কিউ: [Empty]
  • ইভেন্ট: বোতামটি ক্লিক করুন। ইভেন্টের পরে সারি:[Execute OnClick handler(lines 1-4)]
  • ইভেন্ট: অনক্লিক হ্যান্ডলারে প্রথম লাইনটি কার্যকর করুন (উদাহরণস্বরূপ স্ট্যাটাস ডিআইভি মান পরিবর্তন করুন)। ঘটনার পরে সারিতে: [Execute OnClick handler(lines 2-4), re-draw Status DIV with new "Calculating" value]দয়া করে নোট করুন যে ডিওমের পরিবর্তনগুলি তাত্ক্ষণিকভাবে ঘটে যাওয়ার সাথে সাথে সম্পর্কিত ডওম উপাদানটিকে আবার আঁকতে আপনার একটি নতুন ইভেন্টের প্রয়োজন, ডিওএম পরিবর্তনের দ্বারা ট্রিগার করা, যা সারিটির শেষে এসেছিল
  • সমস্যা !!! সমস্যা !!! বিস্তারিত নীচে ব্যাখ্যা করা হয়েছে।
  • ইভেন্ট: হ্যান্ডলারে দ্বিতীয় গণনা কার্যকর করুন (গণনা)। পরে সারিতে: [Execute OnClick handler(lines 3-4), re-draw Status DIV with "Calculating" value]
  • ইভেন্ট: হ্যান্ডলারে তৃতীয় লাইন কার্যকর করুন (ফলাফল ডিআইভি পপুলেট করুন)। পরে সারিতে: [Execute OnClick handler(line 4), re-draw Status DIV with "Calculating" value, re-draw result DIV with result]
  • ইভেন্ট: হ্যান্ডলারে 4 র্থ লাইনটি কার্যকর করুন ("DONE" দিয়ে স্থিতি ডিআইভি স্থাপন করুন)। সারি: [Execute OnClick handler, re-draw Status DIV with "Calculating" value, re-draw result DIV with result; re-draw Status DIV with "DONE" value]
  • ইভেন্ট: হ্যান্ডলার সাব returnথেকে নিহিত কার্যকর onclick। আমরা কিউ থেকে "এক্সিকিউট অনক্লিক হ্যান্ডলার" নিই এবং কিউতে পরবর্তী আইটেমটি সম্পাদন শুরু করি।
  • দ্রষ্টব্য: যেহেতু আমরা ইতিমধ্যে গণনা শেষ করেছি, 3 মিনিট ইতিমধ্যে ব্যবহারকারীর জন্য পেরিয়ে গেছে। পুনরায় ড্র ইভেন্টটি এখনও ঘটেনি !!!
  • ইভেন্ট: "গণনা" মান সহ স্থিতি ডিআইভি পুনরায় আঁকুন। আমরা পুনরায় অঙ্কন করি এবং এটি সারি থেকে সরিয়ে নিই।
  • ইভেন্ট: ফলাফল মান সহ ফলাফল DIV পুনরায় আঁকুন। আমরা পুনরায় অঙ্কন করি এবং এটি সারি থেকে সরিয়ে নিই।
  • ইভেন্ট: "সম্পন্ন" মান সহ স্থিতি ডিআইভি পুনরায় আঁকুন। আমরা পুনরায় অঙ্কন করি এবং এটি সারি থেকে সরিয়ে নিই। তীক্ষ্ণ চোখের দর্শকদের এমনকি "মাইক্রোসেকেন্ডের ভগ্নাংশের জন্য" গণনা করা "মানের ফ্ল্যাশিংয়ের সাথে স্ট্যাটাস ডিআইভি লক্ষ্য করা যায় - গণনার সমাপ্তির পরে

সুতরাং, অন্তর্নিহিত সমস্যাটি হ'ল "স্থিতি" ডিআইভি-র জন্য পুনরায় আঁকার ইভেন্টটি শেষে সারিতে স্থাপন করা হবে, "এক্সিকিউট লাইন 2" ইভেন্টের পরে 3 মিনিট সময় নেয়, সুতরাং আসল পুনরায় অঙ্কনটি ঘটবে না যতক্ষণ না গণনার পরে।


উদ্ধার আসে setTimeout()। এটি কীভাবে সাহায্য করে? কারণ এর মাধ্যমে দীর্ঘ-সম্পাদনকারী কোডটি কল করে setTimeoutআপনি প্রকৃতপক্ষে ২ টি ইভেন্ট তৈরি করেন: setTimeoutনিজেই এক্সিকিউট করুন এবং (0 টাইমআউটের কারণে), কোডটি কার্যকর করার জন্য পৃথক সারি এন্ট্রি।

সুতরাং, আপনার সমস্যা সমাধানের জন্য, আপনি আপনার onClickহ্যান্ডলারটিকে দুটি বয়ান বিবৃতি হিসাবে পরিবর্তন করতে (কোনও নতুন ফাংশনে বা কেবলমাত্র একটি ব্লকের মধ্যে onClick):

  1. "গণনা করা হচ্ছে ... স্থিতিটি ডিআইভিতে minutes 3 মিনিট সময় নিতে পারে" পপুলেশন করুন

  2. সম্পাদন setTimeout()0 সময়সীমার এবং একটি কল সঙ্গে LongCalc()ফাংশন

    LongCalc()ফাংশনটি গতবারের মতো প্রায় একই রকম তবে স্পষ্টতই "গণনা করা হচ্ছে ..." স্ট্যাটাসটি প্রথম পদক্ষেপ হিসাবে ডিআইভি আপডেট নেই; এবং পরিবর্তে এখনই গণনা শুরু করে starts

সুতরাং, ইভেন্টের ক্রম এবং সারিটি এখন কেমন দেখাচ্ছে?

  • কিউ: [Empty]
  • ইভেন্ট: বোতামটি ক্লিক করুন। ইভেন্টের পরে সারি:[Execute OnClick handler(status update, setTimeout() call)]
  • ইভেন্ট: অনক্লিক হ্যান্ডলারে প্রথম লাইনটি কার্যকর করুন (উদাহরণস্বরূপ স্ট্যাটাস ডিআইভি মান পরিবর্তন করুন)। ঘটনার পরে সারিতে: [Execute OnClick handler(which is a setTimeout call), re-draw Status DIV with new "Calculating" value]
  • ইভেন্ট: হ্যান্ডলারে দ্বিতীয় লাইনটি কার্যকর করুন (সেটটাইমআউট কল)। পরে সারিতে: [re-draw Status DIV with "Calculating" value]। আরও 0 সেকেন্ডের জন্য এই সারিটিতে নতুন কিছু নেই।
  • ইভেন্ট: টাইমআউট থেকে অ্যালার্ম বন্ধ হয়, 0 সেকেন্ড পরে। পরে সারিতে: [re-draw Status DIV with "Calculating" value, execute LongCalc (lines 1-3)]
  • ইভেন্ট: "গণনা" মান সহ স্থিতি ডিআইভি পুনরায় আঁকুন । পরে সারিতে: [execute LongCalc (lines 1-3)]। দয়া করে নোট করুন যে অ্যালার্ম বন্ধ হওয়ার আগে এই পুনরায় আঁকার ঘটনাটি আসলে ঘটতে পারে যা ঠিক পাশাপাশি কাজ করে।
  • ...

হুররে! গণনা শুরুর আগেই স্ট্যাটাস ডিআইভি "গণনা ..." -এ আপডেট হয়েছে !!!



নীচে এই উদাহরণগুলি চিত্রিত করে জেএসফিডেলের নমুনা কোডটি দেওয়া হয়েছে: http://jsfiddle.net/C2YBE/31/ :

এইচটিএমএল কোড:

<table border=1>
    <tr><td><button id='do'>Do long calc - bad status!</button></td>
        <td><div id='status'>Not Calculating yet.</div></td>
    </tr>
    <tr><td><button id='do_ok'>Do long calc - good status!</button></td>
        <td><div id='status_ok'>Not Calculating yet.</div></td>
    </tr>
</table>

জাভাস্ক্রিপ্ট কোড: (কার্যকর হয়েছে onDomReadyএবং jQuery 1.9 প্রয়োজন হতে পারে)

function long_running(status_div) {

    var result = 0;
    // Use 1000/700/300 limits in Chrome, 
    //    300/100/100 in IE8, 
    //    1000/500/200 in FireFox
    // I have no idea why identical runtimes fail on diff browsers.
    for (var i = 0; i < 1000; i++) {
        for (var j = 0; j < 700; j++) {
            for (var k = 0; k < 300; k++) {
                result = result + i + j + k;
            }
        }
    }
    $(status_div).text('calculation done');
}

// Assign events to buttons
$('#do').on('click', function () {
    $('#status').text('calculating....');
    long_running('#status');
});

$('#do_ok').on('click', function () {
    $('#status_ok').text('calculating....');
    // This works on IE8. Works in Chrome
    // Does NOT work in FireFox 25 with timeout =0 or =1
    // DOES work in FF if you change timeout from 0 to 500
    window.setTimeout(function (){ long_running('#status_ok') }, 0);
});

12
দুর্দান্ত উত্তর ডিভিকে! এখানে একটি গিস্ট
কুমিকোদা

4
সত্যিই দুর্দান্ত উত্তর, ডিভিকে। কেবল কল্পনা করা সহজ করার জন্য, আমি সেই কোডটি jsfiddle jsfiddle.net/thangchung/LVAaV
ঠাংচুং

4
@ থাংচুং - আমি জেএসফিডেলে আরও ভাল সংস্করণ (2 টি বোতাম, প্রতিটি ক্ষেত্রে একটি করে) তৈরি করার চেষ্টা করেছি। এটি ক্রোম এবং আইই তে একটি ডেমো হিসাবে কাজ করে তবে কোনও কারণে এফএফ-তে নয় - jsfiddle.net/C2YBE/31 দেখুন । : আমি কেন মুক্তিযোদ্ধা এখানে কাজ করে না stackoverflow.com/questions/20747591/...
DVK

1
@ ডিভিকে "ব্রাউজার তার সমস্ত" টোডো "টাস্ক (উভয় ইউআই টাস্ক এবং জাভাস্ক্রিপ্ট কমান্ড) ইভেন্টগুলির ফলে একক সারিতে পরিণত করে"। স্যার আপনি কি এর জন্য উত্স সরবরাহ করতে পারেন? ইমো আর ব্রাউজারগুলির আলাদা আলাদা ইউআই (রেন্ডারিং ইঞ্জিন) এবং জেএস থ্রেড থাকার কথা নয় .... কোনও অপরাধের উদ্দেশ্য নেই .... কেবল শিখতে চাই ..
ভাওয়াই_ডব্লিউ

1
@ ভাব্যা_উ না, সবই এক সুতোয় ঘটে। এই কারণেই দীর্ঘ জেএস গণনাটি ইউআই
শেবা কের্কফফ

88

জাভাস্ক্রিপ্ট টাইমার কীভাবে কাজ করে সে সম্পর্কে জন রেসিগের নিবন্ধটি একবার দেখুন । আপনি যখন একটি সময়সীমা সেট করেন, ইঞ্জিনটি বর্তমান কল স্ট্যাকটি কার্যকর না করা পর্যন্ত এটি আসলে অ্যাসিনক্রোনাস কোডটি সারি করে।



23

বেশিরভাগ ব্রাউজারের মুখ্য থ্রেড নামে একটি প্রক্রিয়া থাকে যা কিছু জাভাস্ক্রিপ্ট কার্য সম্পাদন, ইউআই আপডেটগুলি যেমন: চিত্রাঙ্কন, পুনরায় আঁকা বা রেফ্লো ইত্যাদি responsible

কিছু জাভাস্ক্রিপ্ট এক্সিকিউশন এবং ইউআই আপডেটের কাজগুলি ব্রাউজারের বার্তার কাতারে সারিযুক্ত হয়, তারপরে মৃত্যুদন্ড কার্যকর করতে ব্রাউজারের মূল থ্রেডে প্রেরণ করা হয়।

মূল থ্রেডটি ব্যস্ত থাকাকালীন যখন ইউআই আপডেটগুলি তৈরি করা হয়, তখন বার্তা সারিটিতে কার্যগুলি যুক্ত করা হয়।

setTimeout(fn, 0);fnমৃত্যুদন্ড কার্যকর করার জন্য এই সারিটির শেষে যুক্ত করুন এটি একটি নির্দিষ্ট সময়ের পরে ম্যাসেজের কাতারে যুক্ত করার জন্য একটি কার্য নির্ধারণ করে।


"প্রতিটি জাভাস্ক্রিপ্ট এক্সিকিউশন এবং ইউআই আপডেটের কাজগুলি ব্রাউজার ইভেন্টের ক্যু সিস্টেমে যুক্ত করা হয়, তারপরে সেই কাজগুলি ব্রাউজারের প্রধান ইউআই থ্রেডে সম্পাদনের জন্য প্রেরণ করা হয়।" .... সোর্স দয়া করে?
bhaya_w

4
উচ্চ পারফরম্যান্স জাভাস্ক্রিপ্ট (নিকোলাস জাকাস, স্টোয়ান স্টেফানভ, রস হার্মেস, জুলিয়েন লেকোমতে, এবং ম্যাট সুইনি)
আর্লি

এই জন্য ডাউনভোট add this fn to the end of the queue। সর্বাধিক গুরুত্বপূর্ণ হ'ল যেখানে setTimeoutএই ফানকটি যুক্ত করা হয়, এই লুপ চক্রের শেষ বা পরবর্তী লুপ চক্রের খুব শুরু।
সবুজ

19

এখানে বিরোধমূলক upvated উত্তর রয়েছে, এবং প্রমাণ ছাড়া কাকে বিশ্বাস করবেন তা জানার কোনও উপায় নেই। এখানে প্রমাণ যে @ ডিভিকে সঠিক এবং @ সালভাদোরডালি ভুল। পরের দাবি:

"এবং এই কারণেই: 0 মিলিসেকেন্ডের বিলম্বের সাথে টাইমআউট সেট করা সম্ভব নয় The সর্বনিম্ন মানটি ব্রাউজার দ্বারা নির্ধারিত হয় এবং এটি 0 মিলিসেকেন্ড নয় Histতিহাসিকভাবে ব্রাউজারগুলি এই সর্বনিম্ন 10 মিলিসেকেন্ডে সেট করে, তবে এইচটিএমএল 5 স্পেস এবং আধুনিক ব্রাউজারগুলি এটি 4 মিলিসেকেন্ডে সেট করেছে ""

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

function testSettimeout0 () {
    var startTime = new Date().getTime()
    console.log('setting timeout 0 callback at ' +sinceStart())
    setTimeout(function(){
        console.log('in timeout callback at ' +sinceStart())
    }, 0)
    console.log('starting blocking loop at ' +sinceStart())
    while (sinceStart() < 3000) {
        continue
    }
    console.log('blocking loop ended at ' +sinceStart())
    return // functions below
    function sinceStart () {
        return new Date().getTime() - startTime
    } // sinceStart
} // testSettimeout0

আউটপুট হল:

setting timeout 0 callback at 0
starting blocking loop at 5
blocking loop ended at 3000
in timeout callback at 3033

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

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

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

15

এটি করার একটি কারণ হ'ল কোডটির কার্যকরকরণটিকে একটি পৃথক, পরবর্তী ইভেন্ট লুপে স্থগিত করা। কোনও ধরণের ব্রাউজার ইভেন্টে সাড়া দেওয়ার সময় (উদাহরণস্বরূপ মাউস ক্লিক করুন), কখনও কখনও বর্তমান ইভেন্টটি প্রক্রিয়া করার পরে কেবল অপারেশনগুলি করা প্রয়োজন । দ্যsetTimeout()সুবিধা এটা করতে সহজ উপায়।

এখন এটি সম্পাদনা করুন যে 2015 এটি আমারও লক্ষ্য করা উচিত যে এটিও রয়েছে requestAnimationFrame(), যা একেবারে একই নয় তবে এটি যথেষ্ট পরিমাণে setTimeout(fn, 0)উল্লেখযোগ্য mentioning


এটি যে জায়গাগুলি ব্যবহার করতে দেখেছি সেখানে এটি হ'ল স্পষ্টভাবে। =)
জাইবোট

অবগতির জন্য: এই উত্তর থেকে এখানে মিশে গেছে stackoverflow.com/questions/4574940/...
Shog9

2
একটি পৃথক, পরবর্তী ঘটনা লুপ কোডের মৃত্যুদন্ড মুলতবি হয় কিভাবে আপনি একটি জিনিসটা না: পরবর্তী ঘটনা লুপ ? আপনি কীভাবে বুঝতে পারবেন যে একটি বর্তমান ইভেন্ট লুপটি কী? আপনি কীভাবে জানবেন যে আপনি এখন কোন ইভেন্টের লুপ ঘুরিয়েছেন?
সবুজ

@ ভাল থাকুন, আপনি সত্যিই তা করেন না; জাভাস্ক্রিপ্ট রানটাইম কী হবে তাতে কোনও সরাসরি দৃশ্যমানতা নেই really
পয়েন্টি

অনুরোধএনিমেশনফ্রেমটি আইই এবং ফায়ারফক্সের সাথে আমার যে সমস্যাটি ছিল তা কখনও কখনও ইউআই আপডেট না করে সমাধান করে
ডেভিড

9

এটি পুরানো উত্তর সহ একটি পুরানো প্রশ্ন। আমি এই সমস্যাটিতে একটি নতুন চেহারা যুক্ত করতে চেয়েছিলাম এবং কেন এমন হয় এবং কেন এটি দরকারী তা নয় তার উত্তর দিতে।

সুতরাং আপনার দুটি ফাংশন রয়েছে:

var f1 = function () {    
   setTimeout(function(){
      console.log("f1", "First function call...");
   }, 0);
};

var f2 = function () {
    console.log("f2", "Second call...");
};

এবং তারপরে তাদের f1(); f2();দ্বিতীয়টিকে প্রথমে কার্যকর করা হয়েছে তা দেখতে নিম্নলিখিত ক্রমে তাদের কল করুন ।

এবং এখানেই কারণ: setTimeout0 মিলি সেকেন্ডের সময় বিলম্বের সাথে থাকা সম্ভব নয় । ন্যূনতম মান ব্রাউজার দ্বারা নির্ধারিত হয় এবং এটি 0 মিলিসেকেন্ড নয়। .তিহাসিকভাবে ব্রাউজারগুলি এটি সর্বনিম্ন 10 মিলিসেকেন্ডে সেট করে তবে HTML5 স্পেস এবং আধুনিক ব্রাউজারগুলি এটি 4 মিলিসেকেন্ডে সেট করে is

যদি নেস্টিং স্তরটি 5 এর বেশি হয় এবং সময়সীমা 4 এরও কম হয়, তবে সময়সীমা 4 এ বাড়িয়ে দিন।

মজিলা থেকেও:

একটি আধুনিক ব্রাউজারে 0 এমএস টাইমআউট বাস্তবায়ন করতে, আপনি এখানে বর্ণিত হিসাবে উইন্ডো.পস্টম্যাসেজ () ব্যবহার করতে পারেন ।

নিম্নলিখিত নিবন্ধটি পড়ার পরে পিএস তথ্য নেওয়া হয় ।


1
@ user2407309 আপনি কি মজা করছেন? আপনার মানে এইচটিএমএল 5 স্পেসিফিকেশনটি ভুল এবং আপনি সঠিক? উত্সাহিত করার আগে উত্সগুলি পড়ুন এবং দৃ strong় দাবি করুন। আমার উত্তরটি এইচটিএমএল স্পেসিফিকেশন এবং historicalতিহাসিক রেকর্ডের উপর ভিত্তি করে। পুরোপুরি একই জিনিসটিকে বারবার ব্যাখ্যা করে এমন উত্তরটি না দিয়ে আমি নতুন কিছু যুক্ত করেছি, যা পূর্ববর্তী উত্তরে প্রদর্শিত হয়নি। আমি বলছি না যে এটিই একমাত্র কারণ, আমি কেবল নতুন কিছু প্রদর্শন করছি।
সালভাদোর ডালি

1
এটি ভুল: "এবং এ কারণেই: 0 মিলিসেকেন্ডের বিলম্বের সাথে সেটটাইমআউট করা সম্ভব নয়" " তাই নয়। 4 মিমি বিলম্ব কেন কার্যকর setTimeout(fn,0)তা সম্পর্কিত নয়।
ভ্লাদিমির কর্নিয়া

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

10
সালভাদোর ডালি: আপনি যদি এখানে মাইক্রো ফ্লেম ওয়ারের সংবেদনশীল দিকগুলি উপেক্ষা করেন তবে আপনাকে সম্ভবত এটি স্বীকার করতে হবে যে @ ভ্লাদিমিরকর্নিয়া ঠিক আছে। এটি সত্য যে ব্রাউজারগুলি 0 মিমি 4 মিমি বিলম্বের মানচিত্র করে, তবে তা না করলেও ফলাফলগুলি একই রকম হয়। এখানে ড্রাইভিং প্রক্রিয়াটি হ'ল কোডটি স্ট্যাকের চেয়ে কাতারে চাপ দেওয়া হয়। এই দুর্দান্ত জেএস কনফের উপস্থাপনাটি দেখুন, এটি সমস্যাটি পরিষ্কার করতে সহায়তা করতে পারে: youtube.com/watch?v=8aGhZQkoFbQ
হ্যাশচেঞ্জ

1
আমি কেন বিভ্রান্ত হচ্ছি কেন আপনি ভাবেন যে আপনার যোগ্যতাটি ন্যূনতম 4 এমএসে দেওয়া বিশ্বব্যাপী সর্বনিম্ন 4 এমএস হয়? এইচটিএমএল 5 স্পেস থেকে আপনার উদ্ধৃতিটি যেমন দেখায়, ন্যূনতম কেবলমাত্র 4 এমএস হয় যখন আপনি কলটি setTimeout/ setIntervalপাঁচ স্তরের অধিক গভীর করে থাকেন; যদি আপনার না থাকে, সর্বনিম্ন 0 এমএস (টাইম মেশিনের অভাবের সাথে কী)। মোজিলার ডকগুলি প্রসারিত করে যে পুনরাবৃত্তি করা, কেবল নেস্টেড কেসগুলি কভার করার জন্য নয় (তাই setInterval0 এর ব্যবধানের সাথে সাথে কয়েকবার অবিলম্বে পুনরায় গঠন করা হবে, তারপরে আরও দীর্ঘতর বিলম্ব হবে), তবে setTimeoutন্যূনতম নেস্টিংয়ের সহজ ব্যবহারগুলি অবিলম্বে সারি করার অনুমতি দেয়।
শ্যাডোর্যাঞ্জার

8

যেহেতু এটির একটি সময়কাল পার হচ্ছে 0, আমি মনে করি এটি setTimeoutকার্যকর কোড থেকে প্রবাহিত কোডটি সরিয়ে দেওয়ার জন্য রয়েছে । সুতরাং এটি যদি এমন কোনও ফাংশন হয় যা কিছুটা সময় নিতে পারে তবে এটি পরবর্তী কোডটি কার্যকর করতে বাধা দেয় না।


অবগতির জন্য: এই উত্তর থেকে এখানে মিশে গেছে stackoverflow.com/questions/4574940/...
Shog9

7

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

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

jsfiddle DVK দ্বারা উপলব্ধ প্রকৃতপক্ষে একটি সমস্যা প্রকাশ করে, কিন্তু এটি জন্য তার ব্যাখ্যা সঠিক নয়।

তার কোডে যা ঘটছে তা হ'ল তিনি প্রথম ইভেন্টের কোনও ইভেন্ট হ্যান্ডলার সংযুক্ত clickকরছেন#do বোতামের ।

তারপরে, আপনি যখন আসলে বোতামটি ক্লিক করেন, messageইভেন্ট হ্যান্ডলার ফাংশনটি উল্লেখ করে একটি তৈরি করা হয়, যা এতে যুক্ত হয় message queue। যখন event loopএই বার্তাটি পৌঁছে, এটি একটি সৃষ্টি framejsfiddle ক্লিকের ইভেন্ট হ্যান্ডলার থেকে ফাংশন কল সঙ্গে স্ট্যাক।

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

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

তাহলে এই পাঠ্যটির পার্শ্ব-প্রতিক্রিয়াটি আপডেট হচ্ছে না কেন? কারণ আপনি যখন আছে DOM মধ্যে উপাদান মান পরিবর্তন - আপনি যা করতে পারেন console.log()এর মান অবিলম্বে এটিকে পরিবর্তন করা পর এবং এটা দেখতে যে হয়েছে পরিবর্তন করা হয়েছে (যা শো কেন DVK এর ব্যাখ্যা সঠিক নয়) - ব্রাউজার হ্রাস করার স্ট্যাকের জন্য অপেক্ষা করছে ( onফিরে আসার জন্য হ্যান্ডলার ফাংশন) এবং এভাবে বার্তাটি শেষ হয়ে যায়, যাতে শেষ পর্যন্ত এটি আমাদের রূপান্তর পরিচালনার প্রতিক্রিয়া হিসাবে রানটাইম দ্বারা যুক্ত করা বার্তাটি কার্যকর করতে পারে এবং ইউআইতে সেই রূপান্তরকে প্রতিফলিত করতে পারে ।

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

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

setTimeoutজিনিসটি তখন কাজ করে কেন ? এটি এটি করে, কারণ এটি কার্যকরভাবে দীর্ঘকালীন ক্রিয়াকলাপের কলটিকে নিজের ফ্রেম থেকে সরিয়ে দেয়, windowপ্রসঙ্গে পরে এটি সম্পাদন করার সময়সূচী দেয় , যাতে এটি নিজেই তত্ক্ষণাত্ ফিরে আসতে পারে এবং মেসেজের কাতারে অন্য বার্তাগুলি প্রক্রিয়া করতে দেয়। এবং ধারণাটিটি হ'ল যে ইউআই "অন আপডেট" বার্তাটি জাভাস্ক্রিপ্টে ডিওমে টেক্সট পরিবর্তন করার সময় আমাদের দ্বারা ট্রিগার করা হয়েছিল, দীর্ঘকাল ধরে চলমান ফাংশনের জন্য সাইন করা বার্তার আগে এখন এগিয়ে যায়, যাতে আমরা ব্লক করার আগে ইউআই আপডেট হয় অনেকক্ষণ ধরে.

দ্রষ্টব্য যে) দীর্ঘকাল ধরে চলমান ফাংশনটি চালিত হওয়ার পরেও সমস্ত কিছু অবরুদ্ধ করে রাখে এবং খ) আপনার গ্যারান্টিযুক্ত নেই যে ইউআই আপডেটটি বার্তার কাতারে আসলে এটির আগে। আমার জুন 2018 এর ক্রোম ব্রাউজারে, 0ফিডল যে সমস্যাটি দেখায় - 10 এর দ্বারা একটি মান "ঠিক" করে না। আমি আসলে এটিকে কিছুটা দমিয়ে রেখেছি, কারণ ইউআই আপডেট বার্তাটি তার আগেই সারিবদ্ধ হওয়া উচিত বলে আমার কাছে যৌক্তিক মনে হয়, কারণ "পরে" চালানোর জন্য দীর্ঘস্থায়ী ফাংশন নির্ধারণের আগে এর ট্রিগারটি কার্যকর করা হয়। তবে সম্ভবত ভি 8 ইঞ্জিনে কিছু অপ্টিমাইজেশন রয়েছে যা হস্তক্ষেপ করতে পারে বা আমার বোঝার মধ্যে কেবল অভাব রয়েছে।

ঠিক আছে, তাহলে ব্যবহারে সমস্যা setTimeoutকী, এবং এই বিশেষ কেসের জন্য আরও ভাল সমাধান কী?

প্রথমত, এই জাতীয় setTimeoutইভেন্ট হ্যান্ডলারটি ব্যবহার করে অন্য সমস্যাটি দূর করার চেষ্টা করতে সমস্যাটি অন্যান্য কোডের সাথে বিশৃঙ্খলাবদ্ধ। এখানে আমার কাজ থেকে একটি বাস্তব জীবনের উদাহরণ:

সহকর্মী, ইভেন্ট লুপ সম্পর্কে ভুল-বোধগম্যভাবে বোঝার জন্য, জাভাস্ক্রিপ্টটির রেন্ডারিংয়ের জন্য কিছু টেম্পলেট রেন্ডারিং কোড ব্যবহার করে "থ্রেড" করার চেষ্টা করেছিলেন setTimeout 0। তিনি আর জিজ্ঞাসা করার জন্য এখানে নেই, তবে আমি অনুমান করতে পারি যে সম্ভবত তিনি রেন্ডারিং গতি (যা ফাংশনগুলির প্রত্যাবর্তন নীতি হবে) মাপার জন্য টাইমারগুলি সন্নিবেশ করিয়েছিলেন এবং দেখেছেন যে এই পদ্ধতির সাহায্যে এই ফাংশনটি থেকে ঝাপটায় দ্রুত প্রতিক্রিয়া দেখাবে।

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

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

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

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


3

অন্যটি যা করে তা হ'ল ফাংশনটির অনুরোধটিকে স্ট্যাকের নীচের দিকে ঠেলে দেওয়া, যদি আপনি পুনরাবৃত্তভাবে কোনও ফাংশন কল করে থাকেন তবে স্ট্যাকের ওভারফ্লো প্রতিরোধ করা। এটি একটি whileলুপটির প্রভাব ফেলে তবে জাভাস্ক্রিপ্ট ইঞ্জিনটিকে অন্যান্য অ্যাসিনক্রোনাস টাইমারগুলিকে ফায়ার করতে দেয়।


এই জন্য ডাউনভোট push the function invocation to the bottom of the stack । কি stackবলছ তুমি অস্পষ্ট। সর্বাধিক গুরুত্বপূর্ণ হ'ল যেখানে setTimeoutএই ফানকটি যুক্ত করা হয়, এই লুপ চক্রের শেষ বা পরবর্তী লুপ চক্রের খুব শুরু।
সবুজ

1

সেটটাইমআউট কল করে আপনি পৃষ্ঠাটি সময় দিন যা ব্যবহারকারী যা কিছু করছে তার প্রতিক্রিয়া জানাতে। এটি পৃষ্ঠা লোড চলাকালীন চলমান ফাংশনগুলির জন্য বিশেষভাবে সহায়ক।


1

কিছু অন্যান্য ক্ষেত্রে যেখানে সেটটাইমআউট কার্যকর:

আপনি একটি দীর্ঘ-চলমান লুপ বা গণনাটিকে ছোট ছোট ভাগে বিভক্ত করতে চান যাতে ব্রাউজারটি 'হিমায়িত' না হয় বা "পৃষ্ঠায় স্ক্রিপ্ট ব্যস্ত থাকে" না বলে।

ক্লিক করার সময় আপনি একটি ফর্ম জমা বোতামটি অক্ষম করতে চান তবে আপনি অনক্লিক হ্যান্ডলারের বোতামটি অক্ষম করলে ফর্মটি জমা দেওয়া হবে না। শূন্য সময়ের সাথে সেটটাইমআউট কৌতুক করে, ইভেন্টটি শেষ হতে দেয়, ফর্মটি জমা দেওয়া শুরু করে, তারপরে আপনার বোতামটি অক্ষম করা যায়।


2
অনসামিত ইভেন্টে অক্ষম করা আরও ভাল করা হবে; এটি দ্রুততর হবে এবং ফর্মটি প্রযুক্তিগতভাবে জমা দেওয়ার আগে ফোন করার গ্যারান্টিযুক্ত যেহেতু আপনি জমা দেওয়া বন্ধ করতে পারেন।
ক্রিস

খুবই সত্য. আমি অনুমান করি অনটলিক অক্ষমকরণ প্রোটোটাইপিংয়ের পক্ষে সহজ কারণ আপনি বোতামে অন্লিক = "this.dis اهل = সত্য" টাইপ করতে পারেন তবে জমা দেওয়ার সময় অক্ষম করাতে আরও কিছু কাজ প্রয়োজন।
ফেবস্প্রো

1

কিছু অন্যান্য কোড সম্পূর্ণ হওয়ার আগে ডিউম রেকর্ডিং সম্পর্কে কার্যকর করা উত্তরগুলি লুপ হয়। জাভাস্ক্রিপ্টে জিরো দ্বিতীয় সময়সীমা কোডটি সিউডো-মাল্ট্রিথ্রেড তৈরি করতে সহায়তা করে, যদিও তা না হলেও।

আমি যুক্ত করতে চাই যে জাভাস্ক্রিপ্টে ক্রস ব্রাউজার / ক্রস প্ল্যাটফর্মের শূন্য-দ্বিতীয় সময়সীমার জন্য সর্বোত্তম মানটি আসলে 0 (শূন্য) এর পরিবর্তে প্রায় 20 মিলিসেকেন্ড, কারণ অনেক মোবাইল ব্রাউজারগুলি ঘড়ির সীমাবদ্ধতার কারণে 20 মিলিসেকেন্ডের চেয়ে কম সময়সীমা নিবন্ধন করতে পারে না এএমডি চিপস

এছাড়াও, দীর্ঘ-চলমান প্রক্রিয়াগুলি যা ডোম ম্যানিপুলেশনের সাথে জড়িত না সেগুলি এখন ওয়েব কর্মীদের কাছে প্রেরণ করা উচিত, কারণ তারা জাভাস্ক্রিপ্টের সত্যিকারের মাল্টিথ্রেডেড এক্সিকিউশন সরবরাহ করে।


2
আমি আপনার উত্তর সম্পর্কে কিছুটা সংশয়ী, কিন্তু এটির উন্নতি করেছি কারণ এটি আমাকে ব্রাউজারের মান সম্পর্কে কিছু অতিরিক্ত গবেষণা করতে বাধ্য করেছিল। মান নিয়ে গবেষণা করার সময়, আমি যেখানেই সর্বদা যাই সেখানে যাই, MDN: developer.mozilla.org/en-US/docs/Web/API/window.setTimeout HTML5 spec 4ms বলে। এটি মোবাইল চিপগুলিতে ঘড়ির সীমাবদ্ধতা সম্পর্কে কিছুই বলে না। আপনার বিবৃতি ব্যাক আপ করতে তথ্যের উত্স জন্য একটি হার্ড সময় googling আছে। গুগলের দ্বারা ডার্ট ল্যাঙ্গুয়েজ টাইমার অবজেক্টের পক্ষে সেটটাইমআউট পুরোপুরি সরানো হয়েছে।
জন জাব্রোস্কি

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

1

0-এ সেটটাইমআউট একটি স্থগিত প্রতিশ্রুতি স্থাপনের ধরণে খুব দরকারী, যা আপনি এখনই ফিরে যেতে চান:

myObject.prototype.myMethodDeferred = function() {
    var deferredObject = $.Deferred();
    var that = this;  // Because setTimeout won't work right with this
    setTimeout(function() { 
        return myMethodActualWork.call(that, deferredObject);
    }, 0);
    return deferredObject.promise();
}

1

সমস্যাটি হ'ল আপনি কোন বিদ্যমান উপাদানকে জাভাস্ক্রিপ্ট অপারেশন করার চেষ্টা করছেন। উপাদানটি এখনও লোড করা হয়নি এবং setTimeout()একটি উপাদানকে নিম্নলিখিত উপায়ে লোড করতে আরও সময় দেয়:

  1. setTimeout()ইভেন্টটিকে সংযোজনীয় হতে পারে তাই সমস্ত সিঙ্ক্রোনাস কোডের পরে কার্যকর করা হচ্ছে, আপনার উপাদানটিকে আরও লোড দেওয়ার সময় দেয়। কলব্যাকের মতো অ্যাসিঙ্ক্রোনাস কলব্যাকগুলি ইভেন্টের কাতারেsetTimeout() স্থাপন করা হয় এবং সিঙ্ক্রোনাস কোডের স্ট্যাক ফাঁকা থাকার পরে ইভেন্ট লুপ দ্বারা স্ট্যাকের উপরে রাখা হয় ।
  2. ফাংশনে দ্বিতীয় আর্গুমেন্ট হিসাবে setTimeout()এমএসের জন্য 0 এর মানটি প্রায়শই কিছুটা বেশি থাকে (ব্রাউজারের উপর নির্ভর করে 4-10 মিমি)। setTimeout()কলব্যাকগুলি সম্পাদন করার জন্য এই সামান্য বেশি সময় প্রয়োজন ইভেন্ট লুপের 'টিক্স' (যেখানে একটি টিক স্ট্যাকটি কলব্যাকের দিকে চাপ দিচ্ছে যদি স্ট্যাকটি খালি থাকে) দ্বারা ঘটে। কর্মক্ষমতা এবং ব্যাটারি জীবনের কারণে ইভেন্ট লুপে টিক্সের পরিমাণ নির্দিষ্ট পরিমাণে সীমাবদ্ধ প্রতি সেকেন্ডে 1000 বারের চেয়ে কম

-1

জাভাস্ক্রিপ্ট হ'ল একক থ্রেডেড অ্যাপ্লিকেশন যাতে একযোগে ফাংশন চালানোর অনুমতি না দেয় যাতে এই ইভেন্টটি লুপগুলি ব্যবহার করা যায় achieve সুতরাং সেটটাইমআউট (এফএন, 0) ঠিক কী করে যা এটি টাস্ক কোয়েস্টে ঠেলে দেয় যা আপনার কল স্ট্যাক খালি হলে কার্যকর করা হয়। আমি জানি এই ব্যাখ্যাটি বেশ বিরক্তিকর, তাই আমি আপনাকে এই ভিডিওটি দিয়ে যাওয়ার পরামর্শ দিচ্ছি এটি ব্রাউজারে কীভাবে জিনিসগুলি কাজ করে তা আপনাকে সহায়তা করবে। এই ভিডিওটি দেখুন: - https://www.youtube.com/watch?time_continue=392&v=8aGhZQkoFbQ

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