web-dev-qa-db-ja.com

JavaScriptでは、特定の時間に関数を実行するにはどうすればよいですか?

ダッシュボードをホストするWebサイトがあります。ページのJavaScriptを編集でき、現在5秒ごとに更新しています。

私は今、毎日午前8時にwindow.print()を実行しようとしています。

どうすればこれができますか?

15
user3738622

JavaScriptはこのためのツールではありませんではありません。毎日特定の時間に何かを実行したい場合、ほぼ確実に python または applescript のようなローカルで実行されるものを探しています。


ただし、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時に実行されません(分でこれを実行し始めない限り)毎分をチェックしているため。チェックの精度を上げるために間隔をできるだけ短くすることもできますが、これは過剰です。チェックは毎分ofevery hourofof every dayto if it it is 8 o '時計。

チェックの強度はJavaScriptの性質によるものです。この種のものには、はるかに優れた言語とフレームワークがあります。 JavaScriptは、ロード時にWebページ上で実行されるため、長期にわたる拡張タスクを処理するためのものではありません。

また、これは、実行中のWebページが開いている必要があることにも注意してください。つまり、カウントとチェックを毎分してページが開いていない場合、毎日午前8時にスケジュールされたアクションを発生させることはできません。

あなたはすでに5秒ごとにページを更新していると言います。それが本当であれば、タイマーはまったく必要ありません。ページを更新するたびに確認してください:

_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
}
_

これを使用すると、5秒ごとに更新しているため、秒数もチェックする必要があります。そのため、タスクが重複します。


そうは言っても、 this のようなことをしたり、OS Xでスケジュールされたタスク用のAutomatorワークフローを書いたりすることもできます。

プラットフォームにとらわれない何かが必要な場合は、 Python または Bash を真剣に検討することを検討します。


アップデートとして、 JavaScript for Automation はOS X Yosemiteで導入され、この種のことのためにJavaScriptを使用する実行可能な方法を提供しているようです(ただし、同じコンテキストでJavaScriptを使用していないことは明らかです) ; Appleは、ローカルで別のスクリプト言語を使用するためのインターフェースを提供しているだけです)。

OS Xを使用していて本当にJavaScriptを使用したい場合は、これが適切な方法だと思います。

上記にリンクされたリリースノートは、この執筆時点で存在する唯一のドキュメントのようです(ヨセミテが一般にリリースされてから2か月後)。ただし、一読の価値はあります。 javascript-automation タグでいくつかの例を確認することもできます。

JXAクックブック非常に役立つも参考になりました。

特定の状況に合わせてこのアプローチを少し調整する必要があるかもしれませんが、一般的な概要を説明します。

  1. Automatorで空のアプリケーションを作成します。
    • Automator.app(アプリケーションディレクトリにある必要があります)を開き、新しいドキュメントを作成します。
    • ダイアログから「アプリケーション」を選択します。 Automator new document dialog
  2. JavaScriptアクションを追加します。
    • 次のステップは、実行されるJavaScriptを実際に追加することです。そのためには、まずサイドバーからワークフローに「JavaScriptを実行」アクションを追加します。 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. アプリケーションを保存します。
    • 保存(_File -> Save_または +S)見つけられる場所(またはiCloud)のアプリケーションとしてのファイル。
  5. 実行するようにスケジュールします。
    • カレンダー(またはiCal)を開きます。
    • 新しいイベントを作成し、識別可能な名前を付けます。次に、時間を目的の実行時間(この場合は午前8時)に設定します。
    • イベントを毎日繰り返すように設定します(または毎週、毎月など–ただし、頻繁に実行したい場合があります)。
    • アラート(またはバージョンによってはアラーム)をカスタムに設定します。
    • [ファイルを開く]を選択し、保存したアプリケーションファイルを選択します。
    • アラートのタイミングオプションで[イベント時]を選択します。 GIF instructions for scheduling the event

それでおしまい!アプリケーションファイルに記述したJavaScriptコードは、そのイベントが実行されるように設定されるたびに実行されます。 Automatorでファイルに戻って、必要に応じてコードを変更できるはずです。

42
AstroCB
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を別のタイムスタンプに設定することで、実行時間を簡単に変更できます。

他の人が指摘したように、その考えを実行することがどのように役立つかはわかりません。それが起こるのを確認するには、ページを1日中開いておく必要があります...

また、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();
    }
}

Every8amと同じ方法で実行します。8amが2.5秒進んでいるか遅れているかを調べ、遅れている場合は実行します。

8
DrakaSAN

私はそれが役立つことを願って私の答えを出そうとします:

    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を使用して実行できるタスクは1つだけですが、タスクを再実行する必要がある場合は、startJobAtを呼び出す必要があります。

さようなら

PS

ダイアログボックスなしで自動印刷操作が必要な場合は、Mozillaのプラグイン http://jsprintsetup.mozdev.org/reference.html を使用するか、他のクッパのプラグインを使用することを検討してください。

4
gaetanoM

私は関数を書きました

  • 秒単位の遅延、new Date()形式、およびstringnew 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);
}

これは次のように使用します。

scheduleAt(2, function() {
    console.log("Hello, this function was delayed 2s.");
});

scheduleAt(
    new Date().toString().replace(/:\d{2} /, ':59 '),
    function() {
        console.log("Hello, this function was executed (almost) at the end of the minute.")
    }
);

scheduleAt(new Date(Date.UTC(2014, 9, 31)), function() {
    console.log('Saying in UTC time zone, we are just celebrating Helloween!');
})
2
test30

他のスクリプトから独立しており、ページのパフォーマンスに影響を与えることなく実行されるため、Webワーカーの概念で実行することをお勧めします。

  1. Webワーカーを作成する(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コードでWebワーカーを使用します。

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

それはあなたを助けると思います。

2
Pradeepta