在JavaScript中,如何在特定时间运行函数?

时间:2014-07-14 16:42:32

标签: javascript time intervals

我有一个托管仪表板的网站:我可以在页面上编辑JavaScript,而且我现在每隔五秒刷新一次。

我现在尝试每天早上8点运行window.print()

我怎么能这样做?

6 个答案:

答案 0 :(得分:34)

JavaScript 不是这个工具。如果您希望每天在特定时间运行某些内容,那么您几乎肯定会在寻找本地运行的内容,例如


但是,让我们暂时考虑JavaScript是您唯一的选择。有几种方法可以做到这一点,但我会给你最简单的。

首先,您必须创建new Date()并设置检查间隔以查看小时是否为8(上午8点)。

这将检查每分钟(60000毫秒)以查看它是否是8点钟:

window.setInterval(function(){ // Set interval for checking
    var date = new Date(); // Create a Date object to find out what time it is
    if(date.getHours() === 8 && date.getMinutes() === 0){ // Check the time
        // Do stuff
    }
}, 60000); // Repeat every 60000 milliseconds (1 minute)

它不会在完全 8点钟时执行(除非你在分钟开始正常运行),因为它每分钟检查一次 。您可以减少间隔,因为您希望提高检查的准确性,但这样做太过分了:它会每小时检查每分钟 强烈> 每天,看看它是否是8点钟。

检查的强度取决于JavaScript的性质:对于这类事情,有更好的语言和框架。因为JavaScript在加载时会在网页上运行,所以它并不意味着可以处理持久的扩展任务。

还要意识到这需要在上执行的网页才能打开。也就是说,如果页面没有打开进行计数并检查每分钟,则您无法在每天上午8点进行预定的操作。

你说你已经每五秒刷新一次页面:如果这是真的,你根本就不需要计时器。每次刷新页面时都要检查:

var date = new Date(); // Create Date object for a reference point
if(date.getHours() === 8 && date.getMinutes() === 0 && date.getSeconds() < 10){ // Check the time like above
   // Do stuff
}

有了这个,您还必须检查秒数,因为您每五秒刷新 ,因此您将获得重复的任务。


话虽如此,您可能希望执行this之类的操作,或者为OS X上的计划任务编写Automator工作流程。

如果您需要更多与平台无关的内容,请认真考虑查看PythonBash


作为更新,{X} Yosemite引入了JavaScript for Automation,它似乎提供了一种可行的方式来使用JavaScript来做这类事情(尽管很明显你并没有在同一个环境中使用它) ; Apple只是为您提供了在本地使用其他脚本语言的界面。

如果您使用的是OS X并且真的想使用JavaScript,我认为这是可行的方法。

与上述相关的发行说明似乎是撰写本文时的唯一现有文件(约塞米特向公众发布后约2个月),但它们值得一读。您还可以查看标记以获取一些示例。

我还发现JXA Cookbook 非常非常有帮助。

您可能需要稍微调整一下此方法以根据您的具体情况进行调整,但我会给出一般概述。

  1. 在Automator中创建一个空白的应用程序。
    • 打开Automator.app(它应该在您的Applications目录中)并创建一个新文档。
    • 从对话框中选择&#34;应用程序。&#34; Automator new document dialog
  2. 添加JavaScript操作。
    • 下一步是实际添加将要执行的JavaScript。要做到这一点,首先要添加一个&#34;运行JavaScript&#34;从侧边栏到工作流程的操作。 Drag the JS file into the workflow
  3. 编写JavaScript。

    • 这是您在继续操作之前必须知道自己想要做什么的地方。根据您提供的内容,我假设您要在Safari中加载的页面上执行window.print()。你可以这样做(或者更常见的是,在Safari选项卡中执行任意JS):

      var safari = Application('Safari');
      safari.doJavaScript('window.print();', { in: safari.windows[0].currentTab });
      
    • 您可能需要根据自己的设置调整自己访问的windows中的哪一个。
  4. 保存应用程序。
    • 在您可以找到的位置(或iCloud)中将该文件另存为(File -> Save + S )。
  5. 安排它运行。
    • 打开日历(或iCal)。
    • 创建一个新事件并为其指定一个可识别的名称;然后,将时间设置为所需的运行时间(在这种情况下为上午8:00)。
    • 将事件设置为每天重复(或每周,每月等等 - 但无论如何您都希望自己运行)。
    • 将警报(或警报,具体取决于您的版本)设置为自定义。
    • 选择&#34;打开文件&#34;并选择您保存的应用程序文件。
    • 选择&#34;在活动时#34;用于警报定时选项。 GIF instructions for scheduling the event
  6. 那就是它!每次将该事件设置为运行时,您在应用程序文件中编写的JavaScript代码都将运行。您应该能够在Automator中返回到您的文件,并在需要时修改代码。

答案 1 :(得分:6)

function every8am (yourcode) {
    var now = new Date(),
        start,
        wait;

    if (now.getHours() < 7) {
        start = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 8, 0, 0, 0);
    } else {
        start = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 8, 0, 0, 0);
    }

    wait = start.getTime() - now.getTime();

    if(wait <= 0) { //If missed 8am before going into the setTimeout
        console.log('Oops, missed the hour');
        every8am(yourcode); //Retry
    } else {
        setTimeout(function () { //Wait 8am
            setInterval(function () {
                yourcode();
            }, 86400000); //Every day
        },wait);
    }
}

使用它:

var yourcode = function () {
        console.log('This will print evryday at 8am');
    };
every8am(yourcode);

基本上,获取现在的时间戳,今天早上8点的时间戳,如果及时运行,或者明天早上8点,然后设置一个24小时的间隔来每天运行代码。您可以通过在不同的时间戳设置变量start来轻松更改运行的小时数。

我不知道如何做到这一点,正如其他人指出的那样,你需要整天打开页面才能看到这种情况......

此外,由于您每5秒刷新一次:

function at8am (yourcode) {
    var now = new Date(),
        start = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 8, 0, 0, 0);

    if (now.getTime() >= start.getTime() - 2500 && now.getTime() < start.getTime() + 2500) {
        yourcode();
    }
}

以与每个上午8点相同的方式运行它,看看早上8点是提前还是后面2.5秒,如果确实如此则运行。

答案 2 :(得分:4)

我试着给出答案,希望它有所帮助:

    function startJobAt(hh, mm, code) {
        var interval = 0;
        var today = new Date();
        var todayHH = today.getHours();
        var todayMM = today.getMinutes();
        if ((todayHH > hh) || (todayHH == hh && todayMM > mm)) {
            var midnight = new Date();
            midnight.setHours(24,0,0,0);
            interval = midnight.getTime() - today.getTime() +
                    (hh * 60 * 60 * 1000) + (mm * 60 * 1000);
        } else {
            interval = (hh - todayHH) * 60 * 60 * 1000 + (mm - todayMM) * 60 * 1000;
        }
        return setTimeout(code, interval);
    }

使用startJobAt,你只能执行一个你想要的任务,但是如果你需要重新运行你的任务你可以回忆起startJobAt。

再见

如果您需要自动打印操作,没有对话框,请考虑使用http://jsprintsetup.mozdev.org/reference.html插件用于mozilla或其他插件用于其他插件。

答案 3 :(得分:2)

我写了

的功能
  • 允许以秒为单位表示延迟,new Date()格式和string的{​​{1}}格式
  • 允许取消计时器

这是代码:

new Date

使用如下:

"use strict"
/**
  This function postpones execution until given time.
  @delay might be number or string or `Date` object. If number, then it delay expressed in seconds; if string, then it is parsed with new Date() syntax. Example:
      scheduleAt(60, function() {console.log("executed"); }
      scheduleAt("Aug 27 2014 16:00:00", function() {console.log("executed"); }
      scheduleAt("Aug 27 2014 16:00:00 UTC", function() {console.log("executed"); }
  @code function to be executed
  @context @optional `this` in function `code` will evaluate to this object; by default it is `window` object; example:
      scheduleAt(1, function(console.log(this.a);}, {a: 42})
  @return function which can cancel timer. Example:
      var cancel=scheduleAt(60, function(console.log("executed.");});
      cancel();
      will never print to the console.
*/

function scheduleAt(delay, code, context) {

    //create this object only once for this function
    scheduleAt.conv = scheduleAt.conv || {
        'number': function numberInSecsToUnixTs(delay) {
            return (new Date().getTime() / 1000) + delay;
        },
        'string': function dateTimeStrToUnixTs(datetime) {
            return new Date(datetime).getTime() / 1000;
        },
        'object': function dateToUnixTs(date) {
            return date.getTime() / 1000;
        }
    };

    var delayInSec = scheduleAt.conv[typeof delay](delay) - (new Date().getTime() / 1000);

    if (delayInSec < 0) throw "Cannot execute in past";

    if (debug) console.log('executing in', delayInSec, new Date(new Date().getTime() + delayInSec * 1000))

    var id = setTimeout(
        code,
        delayInSec * 1000
    );

    //preserve as a private function variable setTimeout's id
    return (function(id) {
        return function() {
            clearTimeout(id);
        }
    })(id);
}

答案 4 :(得分:1)

我建议在Web Worker概念中执行此操作,因为它独立于其他脚本并在不影响页面性能的情况下运行。

  1. 创建一个Web worker(demo_worker.js)

    var i = 0;
    var date = new Date();
    var counter = 10;
    var myFunction = function(){
        i = i + 1;
        clearInterval(interval);
        if(date.getHours() === 8 && date.getMinutes() === 0) {
            counter = 26280000;
            postMessage("hello"+i);
        }    
        interval = setInterval(myFunction, counter);
    }
    var interval = setInterval(myFunction, counter);
    
  2. 在Ur代码中使用网络工作者,如下所示。

    var w;    
    function startWorker() {
     if (typeof(Worker) !== "undefined") {
         if (typeof(w) == "undefined") {
             w = new Worker("demo_worker.js");
             w.onmessage = function(event) {
                 window.print();
             };
         } else {
             document.getElementById("result").innerHTML = "Sorry, your browser does not support HTML5 Web Workers";
         }
     }
    }
    
  3. 我认为它会对你有所帮助。

答案 5 :(得分:0)

经过一个小时的思考,我做出了最小的解决方案。 它正好在早上 8 点运行。 (am 可配置)

如果我的英语不好,非常抱歉。

const am = 8; //hour when you want code to run
let dateNow = new Date();
let waitTime = +new Date(dateNow.toDateString())+(dateNow.getHours()>am?86400000:0)+am*3600000-dateNow;
//don't mind the formula
setTimeout(function runAt8AM(){
    // Do something every day at 8 am

    setTimeout(runAt8AM, 86400000);
},waitTime)