programing

밀리 초 지연 값이 큰 경우 setTimeout ()이 "중단"되는 이유는 무엇입니까?

nasanasas 2020. 9. 1. 07:35
반응형

밀리 초 지연 값이 큰 경우 setTimeout ()이 "중단"되는 이유는 무엇입니까?


큰 밀리 초 값을에 전달할 때 예기치 않은 동작이 발생했습니다 setTimeout(). 예를 들어

setTimeout(some_callback, Number.MAX_VALUE);

setTimeout(some_callback, Infinity);

두 가지 모두 지연으로 큰 숫자 대신 some_callback통과 한 것처럼 거의 즉시 실행 0됩니다.

왜 이런 일이 발생합니까?


이는 지연을 저장하기 위해 32 비트 정수를 사용하는 setTimeout 때문이므로 허용되는 최대 값은

2147483647

시도하면

2147483648

문제가 발생합니다.

나는 이것이 JS 엔진에서 어떤 형태의 내부 예외를 일으키고 함수가 전혀 발생하지 않고 즉시 실행되도록 가정 할 수 있습니다.


여기에 몇 가지 설명이 있습니다. http://closure-library.googlecode.com/svn/docs/closure_goog_timer_timer.js.source.html

시간 초과 값이 너무 커서 부호있는 32 비트 정수에 맞지 않을 경우 FF, Safari 및 Chrome에서 오버플로가 발생하여 시간 초과가 즉시 예약 될 수 있습니다. 24.8 일은 브라우저가 열린 상태로 유지 될 수있는 합리적인 기대치를 초과하므로 이러한 시간 제한을 예약하지 않는 것이 더 합리적입니다.


당신이 사용할 수있는:

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);
}

만료 된 세션으로 사용자를 자동으로 로그 아웃하려고 할 때이 문제를 발견했습니다. 내 솔루션은 하루 후에 시간 제한을 재설정하고 clearTimeout을 사용하도록 기능을 유지하는 것입니다.

다음은 약간의 프로토 타입 예제입니다.

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();

여기 타이머에 노드 문서를 체크 아웃 : https://nodejs.org/api/timers.html (JS에 걸쳐 같은 가정은 이러한 유비쿼터스 용어는 이벤트 루프 지금 기초를 잘 이후로

요컨대 :

When delay is larger than 2147483647 or less than 1, the delay will be set to 1.

and delay is:

The number of milliseconds to wait before calling the callback.

Seems like your timeout value is being defaulted to an unexpected value along these rules, possibly?


Can't comment but to answer all the people. It takes unsigned value ( you can't wait negative milliseconds obviously ) So since max value is "2147483647" when you enter a higher value it start going from 0.

Basically delay = {VALUE} % 2147483647.

So using delay of 2147483648 would make it 1 millisecond, therefore, instant proc.


Number.MAX_VALUE

is actually not an integer. The maximum allowable value for setTimeout is likely 2^31 or 2^32. Try

parseInt(Number.MAX_VALUE) 

and you get 1 back instead of 1.7976931348623157e+308.

참고URL : https://stackoverflow.com/questions/3468607/why-does-settimeout-break-for-large-millisecond-delay-values

반응형