বড় মিলিসেকেন্ড বিলম্ব মানগুলির জন্য সেটটাইমআউট () "ব্রেক" কেন?


104

একটি বড় মিলিসেকেন্ড মানটি পাস করার সময় আমি কিছু অপ্রত্যাশিত আচরণ পেয়েছিলাম setTimeout()। এই ক্ষেত্রে,

setTimeout(some_callback, Number.MAX_VALUE);

এবং

setTimeout(some_callback, Infinity);

উভয়ই some_callbackপ্রায় তত্ক্ষণাত্ চালানোর কারণ হয়, যেন আমি 0দেরি হিসাবে বড় সংখ্যার পরিবর্তে পাস করি ।

কেন এমন হয়?

উত্তর:


143

এটি বিলম্ব সঞ্চয় করতে 32 বিট ইন্টি ব্যবহার করে সেটটাইমআউটের কারণে এটি অনুমোদিত সর্বাধিক মান হবে

2147483647

যদি তুমি চেষ্টা কর

2147483648

আপনি আপনার সমস্যা ঘটবে।

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


1
ঠিক আছে, এটা বোঝা যায়। আমি অনুমান করছি এটি আসলে কোনও অভ্যন্তরীণ ব্যতিক্রম বাড়ে না। পরিবর্তে, আমি এটি দেখতে পাচ্ছি যে (1) একটি পূর্ণসংখ্যার অতিরিক্ত প্রবাহ ঘটায় বা (2) অভ্যন্তরীণভাবে বিলম্বকে স্বাক্ষরবিহীন 32-বিট ইনট মান হিসাবে চাপ দিচ্ছে। যদি (1) কেস হয় তবে আমি বিলম্বের জন্য সত্যই একটি নেতিবাচক মানটি পার করছি। যদি এটি (2) হয়, তবে এর মতো কিছু delay >>> 0ঘটে যায়, তাই বিলম্বটি শূন্য হয়। যে কোনও উপায়ে, 32-বিট স্বাক্ষরযুক্ত ইন্ট হিসাবে বিলম্ব সঞ্চিত রয়েছে এই আচরণটি ব্যাখ্যা করে। ধন্যবাদ!
ম্যাট বল

পুরানো আপডেট, তবে আমি সবেমাত্র সীমাটি পেয়েছি 49999861776383( 49999861776384
কলব্যাকটি

7
@ ম্যাক্সপ এর কারণ49999861776383 % 2147483648 === 2147483647
ডেভিড দা সিলভা কনটেন

@ ডেভিডডাসিলভা কনটেন এই মুহূর্তে দেরী করেছেন, তবে আপনি আরও ব্যাখ্যা করতে পারেন? 2147483647 কেন সীমা নয় তা বুঝতে পারি না?
নিক কোড 25'18

2
@ নিককোড উভয় সংখ্যা একই পরিমাণে বিলম্ব করবে (যেমন 49999861776383 স্বাক্ষরিত 32 বিট দৃষ্টিকোণ থেকে 2147483647 এর সমান)। এগুলিকে বাইনারি লিখুন, এবং শেষ 31 টি বিট নিন, সেগুলি সব 1 হবে।
মার্ক ফিশার

24

তুমি ব্যবহার করতে পার:

function runAtDate(date, func) {
    var now = (new Date()).getTime();
    var then = date.getTime();
    var diff = Math.max((then - now), 0);
    if (diff > 0x7FFFFFFF) //setTimeout limit is MAX_INT32=(2^31-1)
        setTimeout(function() {runAtDate(date, func);}, 0x7FFFFFFF);
    else
        setTimeout(func, diff);
}

2
এটি দুর্দান্ত, তবে পুনরাবৃত্তির কারণে আমরা ক্লিয়ারটাইমআউট ব্যবহারের দক্ষতাটি looseিলা করেছি।
অ্যালান নিনিহুইস

2
আপনি যদি আপনার বুককিপিং করেন এবং টাইমআউট প্রতিস্থাপন করেন তবে আপনি এই ফাংশনটির অভ্যন্তরে বাতিল করতে চান তবে সত্যই আপনি এটি বাতিল করার ক্ষমতা হারাবেন না।
চরলাগ

23

এখানে কিছু ব্যাখ্যা: http://closure-library.googlecode.com/svn/docs/closure_goog_timer_timer.js.source.html

একটি স্বাক্ষরিত 32-বিট পূর্ণসংখ্যার সাথে মানানসই টাইমআউট মানগুলি এফএফ, সাফারি এবং Chrome এ ওভারফ্লো হতে পারে, ফলস্বরূপ সময়সীমাটি তত্ক্ষণাত নির্ধারিত হয়ে যায়। ব্রাউজারের উন্মুক্ত থাকার জন্য ২৪.৮ দিন যুক্তিসঙ্গত প্রত্যাশার বাইরে থাকায় এই সময়সীমাগুলি নির্ধারণ না করার বিষয়টি আরও বেশি বোঝা যায়।


2
ওয়ারপেকের উত্তরটি অনেক অর্থবহ করে - একটি নোড.জেএস সার্ভারের মতো দীর্ঘ চলমান প্রক্রিয়াটি একটি ব্যতিক্রমের মতো শোনাতে পারে তবে সত্যি বলতে আপনি যদি এমন কিছু পেয়ে থাকেন যা আপনি ঠিক 24 এবং মিলিসেকেন্ড যথার্থতার সাথে কিছুদিনের মধ্যে ঘটেছিল তা নিশ্চিত করতে চান তারপরে আপনার সেটটাইমআউটের চেয়ে সার্ভার এবং মেশিনের ত্রুটির ক্ষেত্রে আরও শক্তিশালী কিছু ব্যবহার করা উচিত ...
cfogelberg

@ সিফোগেলবার্গ, আমি এফএফ বা এর কোনও প্রয়োগ বাস্তবায়ন দেখিনি setTimeout(), তবে আমি আশা করব যে তারা ঘুম থেকে ওঠার সময় তারিখ এবং সময় গণনা করবে এবং কিছু এলোমেলোভাবে সংজ্ঞায়িত টিকের কাউন্টারকে হ্রাস করবে না ... (একজন আশা করতে পারেন , কমপক্ষে)
অ্যালেক্সিস উইল্ক

2
আমি একটি সার্ভারে নোডজেএসে জাভাস্ক্রিপ্ট চালাচ্ছি, 24.8 দিন এখনও ভাল, তবে আমি 1 মাস (30 দিন) বলার জন্য একটি কলব্যাক সেট করার জন্য আরও যুক্তিযুক্ত উপায়ের সন্ধান করছি। এর জন্য যাওয়ার উপায় কী হবে?
পল

1
আমি নিশ্চিতভাবেই, ব্রাউজার উইন্ডোজ 24.8 দিনের চেয়ে বেশি সময় খোলা ছিল। এটা আমার কাছে উদ্ভট যে ব্রাউজারগুলি অভ্যন্তরীণভাবে রোনেনের সমাধানের মতো কিছু না করে, কমপক্ষে MAX
ائشE_INTEGER

1
কে বলে? আমি আমার ব্রাউজারটি 24 দিনের চেয়ে বেশি সময় খোলা রাখি ...;)
পিট অ্যালভিন

2

টাইমারে নোড ডকটি এখানে এখানে দেখুন: https://nodejs.org/api/timers.html (জেএসের পাশাপাশি একই ধারণা করা যেহেতু এখন ইভেন্ট লুপ ভিত্তিতে এটি এমন একটি সর্বব্যাপী শব্দ)

সংক্ষেপে:

যখন বিলম্বটি 2147483647 এর চেয়ে বড় বা 1 এর চেয়ে কম হয়, তখন বিলম্বটি 1 তে সেট করা হবে।

এবং বিলম্ব হ'ল:

কলব্যাক কল করার আগে অপেক্ষা করার মতো মিলিসেকেন্ডের সংখ্যা।

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


1

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

এখানে একটি সামান্য নমুনা উদাহরণ:

Timer = function(execTime, callback) {
    if(!(execTime instanceof Date)) {
        execTime = new Date(execTime);
    }

    this.execTime = execTime;
    this.callback = callback;

    this.init();
};

Timer.prototype = {

    callback: null,
    execTime: null,

    _timeout : null,

    /**
     * Initialize and start timer
     */
    init : function() {
        this.checkTimer();
    },

    /**
     * Get the time of the callback execution should happen
     */
    getExecTime : function() {
        return this.execTime;
    },

    /**
     * Checks the current time with the execute time and executes callback accordingly
     */
    checkTimer : function() {
        clearTimeout(this._timeout);

        var now = new Date();
        var ms = this.getExecTime().getTime() - now.getTime();

        /**
         * Check if timer has expired
         */
        if(ms <= 0) {
            this.callback(this);

            return false;
        }

        /**
         * Check if ms is more than one day, then revered to one day
         */
        var max = (86400 * 1000);
        if(ms > max) {
            ms = max;
        }

        /**
         * Otherwise set timeout
         */
        this._timeout = setTimeout(function(self) {
            self.checkTimer();
        }, ms, this);
    },

    /**
     * Stops the timeout
     */
    stopTimer : function() {
        clearTimeout(this._timeout);
    }
};

ব্যবহার:

var timer = new Timer('2018-08-17 14:05:00', function() {
    document.location.reload();
});

এবং আপনি stopTimerপদ্ধতিটি দিয়ে এটি সাফ করতে পারেন :

timer.stopTimer();

0

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

মূলত বিলম্ব = {VALUE}% 2147483647।

সুতরাং 2147483648 দেরি ব্যবহার করে এটি 1 মিলিসেকেন্ডে পরিণত হবে, তাই তাত্ক্ষণিক প্রকোপ।


-2
Number.MAX_VALUE

আসলে কোনও পূর্ণসংখ্যা নয়। সেটটাইমআউটের সর্বোচ্চ অনুমোদিত মান সম্ভবত 2 value 31 বা 2 ^ 32। চেষ্টা

parseInt(Number.MAX_VALUE) 

এবং আপনি 1.7976931348623157e + 308 এর পরিবর্তে 1 ফিরে পাবেন।


13
এটি ভুল: Number.MAX_VALUEএকটি পূর্ণসংখ্যা। এটি সংখ্যার 17976931348623157 পরে 292 জিরো সহ। কারণ parseIntরিটার্ন 1কারণ এটি প্রথম একটি স্ট্রিং তার যুক্তি পরিবর্তন করে এবং তারপর স্ট্রিং বাঁ দিক থেকে ডানদিকে অনুসন্ধান করুন। এটি .(যা কোনও সংখ্যা নয়) সন্ধান করার সাথে সাথে এটি বন্ধ হয়ে যায়।
পউয়ান

1
যাইহোক, আপনি যদি কোনও পূর্ণসংখ্য হয় কিনা তা পরীক্ষা করতে চান, ES6 ফাংশনটি ব্যবহার করুন Number.isInteger(foo)। তবে এটি এখনও সমর্থিত নয়, আপনি এর Math.round(foo) === fooপরিবর্তে ব্যবহার করতে পারেন ।
Pauan

2
@ পন, বাস্তবায়ন হিসাবে বিবেচিত, Number.MAX_VALUEএটি একটি পূর্ণসংখ্যা নয়, তবে একটি double। সুতরাং এটি আছে ... একটি ডাবল একটি পূর্ণসংখ্যার প্রতিনিধিত্ব করতে পারে, যদিও এটি জাভাস্ক্রিপ্টে 32 বিটের পূর্ণসংখ্যা সংরক্ষণ করতে ব্যবহৃত হয়।
অ্যালেক্সিস উইল্ক

1
@ অ্যালেক্সিসওয়িল্ক হ্যাঁ, অবশ্যই জাভাস্ক্রিপ্ট সমস্ত সংখ্যা 64-বিট ভাসমান পয়েন্ট হিসাবে প্রয়োগ করে । যদি "পূর্ণসংখ্যার" দ্বারা আপনি "32-বিট বাইনারি" বলতে চান তবে Number.MAX_VALUEএটি পূর্ণসংখ্যা নয়। তবে যদি "পূর্ণসংখ্যার" দ্বারা আপনি "একটি পূর্ণসংখ্যা" এর মানসিক ধারণাটি বোঝায় তবে এটি একটি পূর্ণসংখ্যা। জাভাস্ক্রিপ্টে, যেহেতু সমস্ত সংখ্যা bit৪-বিট ভাসমান বিন্দু, তাই "পূর্ণসংখ্যা" এর মানসিক ধারণা সংজ্ঞাটি ব্যবহার করা সাধারণ।
Pauan

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