【问题标题】:JavaScript interval function to count datetime用于计算日期时间的 JavaScript 间隔函数
【发布时间】:2018-08-18 20:18:09
【问题描述】:

我有一个函数可以返回两个日期时间之间的剩余时间,目前如果我刷新我会得到当前时间到那个特定日期。目前它只在我刷新时返回正确的剩余时间,我尝试设置创建一个 setinterval 函数,以便我每隔几秒获取一次时间,但它不会每秒运行该函数。

到目前为止我的代码:

import moment from 'moment';

const calc = {

    vars: {
        interval: null,
        releaseDate: null,
        currentDate: null
    },

    elements: {
        releaseAt: document.getElementById('release-at'), // 2018-08-31 14:24:00
        currentDate: document.getElementById('current-date') // 2018-08-18 17:32:59
    },

    render () {
        moment().format();
        this.nextTick();
        this.vars.interval = setInterval(this.nextTick(), 1000);
    },

    nextTick () {
        let releaseDate = moment(this.elements.releaseAt.value);
        let currentDate = moment(this.elements.currentDate.value);

        if (currentDate.isBefore(releaseDate)) {
            currentDate.add(1, 'second');
            const diff = releaseDate.diff(currentDate);
            const diffDuration = moment.duration(diff);
            const difference = +releaseDate - +currentDate;

            return console.log(`
                ${diffDuration.months()} months
                ${diffDuration.days()} days
                ${diffDuration.hours()} hours
                ${diffDuration.minutes()} minutes
                ${diffDuration.seconds()} seconds left!`);
        } 

        console.log('boom! End ticker');

        return clearInterval(this.vars.interval);
    }

};

calc.render();

电流输出

            0 months
            12 days
            20 hours
            51 minutes
            0 seconds left!

【问题讨论】:

    标签: javascript momentjs setinterval


    【解决方案1】:

    让间隔工作

    这是你写的:

    setInterval(this.nextTick(), 1000); 
    

    ...当您可能是这个意思时:

    setInterval(this.nextTick, 1000);  
    

    在第一个示例中,this.nextTick()setInterval 之前被评估,因此间隔尝试处理nextTick() 的返回值而不是函数本身。如果nextTick() 返回一个函数,这将很有用,但在这种情况下,它返回一个没有返回值的clearInterval() —— 所以你最终每秒运行一次null

    在第二个示例中,函数本身就是将在间隔上运行的内容。这基本上是一种不那么冗长的写作方式:

    setInterval(function() { this.nextTick() }, 1000)
    

    ...但这在这里也行不通,因为nextTick() 依赖于保留相同的this;在裸函数调用中this 将恢复为 Window 对象,而不是您的 calc。保留this 最容易使用粗箭头函数完成:

    setInterval(()=>{this.nextTick()}, 1000);
    

    在每个间隔更新时间

    同时,第二个不相关的问题:您试图在每个刻度上使用 currentDate.add(1, 'second') 递增内部 currentDate 变量,但从未在任何地方分配该新值 - 并且还从(未修改) 每次输入字段,这意味着您总是会得到相同的结果。相反,您可以将新值写入输入字段,它将在下一个刻度时被拾取:

    this.elements.currentDate.value = currentDate.add(1, 'second');
    

    (或者,或者,如果currentDate 为空,您只能从表单字段中读取,否则仅取决于内部变量。或者更好的是,因为您要查找的是当前时间,请跳过表单字段内部变量,只需使用Date()

    一般而言,最安全的做法是依赖一个事实来源,而不是同时使用内部变量和 DOM 元素来保存相同的数据,并且必须使它们保持同步。)

    工作示例:

    const calc = {
    
        vars: {
            interval: null,
            releaseDate: null,
            currentDate: null
        },
    
        elements: {
            releaseAt: document.getElementById('release-at'), // 2018-08-31 14:24:00
            currentDate: document.getElementById('current-date') // 2018-08-18 17:32:59
        },
    
        render () {
            moment().format();
            this.nextTick();
            this.vars.interval = setInterval(()=>{this.nextTick()}, 1000);
        },
    
        nextTick () {
            let releaseDate = moment(this.elements.releaseAt.value);
            let currentDate = moment(this.elements.currentDate.value);
    
            if (currentDate.isBefore(releaseDate)) {
                this.elements.currentDate.value = currentDate.add(1, 'second');
                const diff = releaseDate.diff(currentDate);
                const diffDuration = moment.duration(diff);
                const difference = +releaseDate - +currentDate;
    
                return console.log(`
                    ${diffDuration.months()} months
                    ${diffDuration.days()} days
                    ${diffDuration.hours()} hours
                    ${diffDuration.minutes()} minutes
                    ${diffDuration.seconds()} seconds left!`);
            } 
    
            console.log('boom! End ticker');
    
            return clearInterval(this.vars.interval);
        }
    
    };
    
    calc.render();
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
    
    <input id="release-at" value="2018-08-31 14:24:00">
    <input id="current-date" value="2018-08-18 17:32:59">

    【讨论】:

    • 嗨,函数现在每秒运行一次,但在第一次调用后它不会再减去 1 秒,因此调用这样的函数 foo() 和 foo 有什么区别
    • 我刚刚更新了答案,修复了永远不变的时间;还将添加更多关于 foo() 与 foo 的解释。
    • 我可能需要一些睡眠,但这不应该每秒更新每个元素的 innerHtml 吗? kopy.io/qaFy9
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-26
    • 2020-02-14
    相关资源
    最近更新 更多