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

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

setTimeout(some_callback, Number.MAX_VALUE);

setTimeout(some_callback, Infinity);

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

왜 이런 일이 발생합니까?



답변

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

2147483647

시도하면

2147483648

문제가 발생합니다.

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


답변

당신이 사용할 수있는:

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


답변

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

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


답변

여기에서 Timers의 노드 문서를 확인하세요 : https://nodejs.org/api/timers.html (현재 이벤트 루프 기반에서 이러한 보편적 인 용어이기 때문에 js에서도 동일하다고 가정 합니다.

요컨대 :

지연이 2147483647보다 크거나 1보다 작 으면 지연이 1로 설정됩니다.

지연은 다음과 같습니다.

콜백을 호출하기 전에 대기하는 시간 (밀리 초)입니다.

시간 초과 값이 이러한 규칙에 따라 예상치 못한 값으로 기본 설정되는 것 같습니다.


답변

만료 된 세션으로 사용자를 자동으로 로그 아웃하려고 할 때이 문제를 발견했습니다. 내 솔루션은 하루 후에 시간 제한을 재설정하고 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();


답변

댓글을 달 수는 없지만 모든 사람들에게 대답합니다. 부호없는 값을 사용합니다 (음수 밀리 초는 당연히 기다릴 수 없습니다). 따라서 최대 값은 “2147483647”이므로 더 높은 값을 입력하면 0부터 시작됩니다.

기본적으로 지연 = {VALUE} % 2147483647.

따라서 2147483648 지연을 사용하면 1 밀리 초가되므로 즉시 처리됩니다.


답변

Number.MAX_VALUE

실제로 정수가 아닙니다. setTimeout의 최대 허용 값은 2 ^ 31 또는 2 ^ 32입니다. 시험

parseInt(Number.MAX_VALUE) 

1.7976931348623157e + 308 대신 1 개를 돌려받습니다.