38
 fs.watch( 'example.xml', function ( curr, prev ) {
   // on file change we can read the new xml
   fs.readFile( 'example.xml','utf8', function ( err, data ) {
     if ( err ) throw err;
     console.dir(data);
     console.log('Done');
   });
 });

出力:

  • いくつかのデータ
  • 完了X1
  • いくつかのデータ
  • 完了X2

それは私の使用上の誤りか..?

4

15 に答える 15

44

fs.watchAPI :

  1. 不安定です
  2. 繰り返しの通知に関する「動作」を知っています。具体的には、WindowsのケースはWindowsの設計の結果であり、単一のファイルの変更はWindowsAPIへの複数の呼び出しである可能性があります
于 2012-10-19T17:53:24.600 に答える
20

私は次のことを行うことでこれを考慮に入れます:

var fsTimeout

fs.watch('file.js', function(e) {

    if (!fsTimeout) {
        console.log('file.js %s event', e)
        fsTimeout = setTimeout(function() { fsTimeout=null }, 5000) // give 5 seconds for multiple events
    }
}
于 2013-09-15T03:38:54.853 に答える
17

chokidarhttps://github.com/paulmillr/chokidar )を使用することをお勧めします。これはfs.watch:よりもはるかに優れています。

そのREADME.mdにコメントする:

Node.js fs.watch

  • OSXではファイル名を報告しません。
  • OS XでSublimeなどのエディターを使用している場合、イベントはまったく報告されません。
  • 多くの場合、イベントを2回報告します。
  • ほとんどの変更をとして出力しrenameます。
  • 他にもたくさんの問題があります
  • ファイルツリーを再帰的に監視する簡単な方法を提供しません。

Node.js fs.watchFile

  • イベント処理がほぼ同じくらい悪い。
  • また、再帰的な監視も提供しません。
  • CPU使用率が高くなります。
于 2015-10-09T22:07:40.890 に答える
12

ファイルの変更を監視する必要がある場合は、私の小さなライブラリon-file-changeを確認できます。発生したイベント間でファイルsha1ハッシュをチェックしますchange

複数のイベントが発生した理由の説明:

特定の状況では、単一の作成イベントが、コンポーネントによって処理される複数の作成済みイベントを生成することに気付く場合があります。たとえば、FileSystemWatcherコンポーネントを使用してディレクトリ内の新しいファイルの作成を監視し、メモ帳を使用してファイルを作成してテストすると、ファイルが1つしか作成されていなくても、2つのCreatedイベントが生成される場合があります。これは、メモ帳が書き込みプロセス中に複数のファイルシステムアクションを実行するためです。メモ帳は、ファイルのコンテンツを作成してからファイル属性を作成するバッチでディスクに書き込みます。他のアプリケーションも同じように動作する場合があります。FileSystemWatcherはオペレーティングシステムのアクティビティを監視するため、これらのアプリケーションが起動するすべてのイベントが取得されます。

ソース

于 2013-04-10T21:55:31.827 に答える
4

私のカスタムソリューション

私は個人的にreturn、何かをチェックするときにコードのブロックが実行されないようにするために使用するのが好きなので、ここに私のメソッドがあります:

var watching = false;
fs.watch('./file.txt', () => {
    if(watching) return;
    watching = true;

    // do something

    // the timeout is to prevent the script to run twice with short functions
    // the delay can be longer to disable the function for a set time
    setTimeout(() => {
        watching = false;
    }, 100);
};

この例を自由に使用して、コードを簡略化してください。他のモジュールを使用するよりも良いとは言えないかもしれませんが、それはかなりうまく機能します!

于 2017-11-26T23:48:38.180 に答える
1

私はこの問題に初めて取り組んでいるので、これまでのすべての答えはおそらく私の解決策よりも優れていますが、どれも私の場合に100%適していなかったので、少し異なるものを思いつきました–私はXORを使用しました0と1の間の整数を反転する操作。ファイルのすべてのイベントを効果的に追跡し、無視します。

var targetFile = "./watchThis.txt"; 
var flippyBit = 0; 

fs.watch(targetFile, {persistent: true}, function(event, filename) {

      if (event == 'change'){
        if (!flippyBit) {
          var data = fs.readFile(targetFile, "utf8", function(error, data) {
            gotUpdate(data);
          })
        } else {
          console.log("Doing nothing thanks to flippybit.");              
        }
        flipBit(); // call flipBit() function
      }
    });

// Whatever we want to do when we see a change
function gotUpdate(data) {
    console.log("Got some fresh data:");
    console.log(data);
    }


// Toggling this gives us the "every second update" functionality

function flipBit() {
    flippyBit = flippyBit ^ 1;
}

私が見ているファイルは、仮想的に非常に頻繁に正当な更新を取得する可能性があるため、時間関連の関数(jwymanmの回答など)を使用したくありませんでした。また、監視しているファイルは1つだけなので、ErikPが提案するような監視対象ファイルのリストは使用したくありませんでした。JanŚwięckiのソリューションは、私が低電力環境で非常に短く単純なファイルに取り組んでいるため、やり過ぎのように見えました。最後に、ベルナドの答えは私を少し緊張させました–最初の処理を完了する前に到着した場合、2番目の更新を無視するだけであり、そのような不確実性を処理することはできません。誰かがこの非常に特定のシナリオに自分自身を見つけるとしたら、私が使用したアプローチにいくつかのメリットがあるかもしれませんか?何か大きな問題がある場合は、この回答を知らせて編集してください。これまでのところ、うまく機能しているようです。

注:明らかに、これは、実際の変更ごとに正確に2つのイベントを取得することを強く前提としています。私は明らかにこの仮定を注意深くテストし、その限界を学びました。これまでのところ、私はそれを確認しました:

  • Atomエディターでファイルを変更して保存すると、2つの更新がトリガーされます
  • touch2つの更新をトリガーします
  • >(ファイルの内容を上書きする)を介した出力リダイレクトは、2つの更新をトリガーします
  • 経由で追加すると、 >> 1回の更新がトリガーされることがあります。*

行動の違いについては完全に正当な理由を考えることができますが、それを計画するために何かが起こっている理由を知る必要はありません。自分の環境と状況で自分自身をチェックしたいと思うことを強調したかっただけです。あなた自身のユースケースの(duh)そしてインターネット上の自白の馬鹿を信用しないでください。そうは言っても、予防策を講じても、今のところ奇妙なことはありません。

*完全な開示、私は実際にこれが起こっている理由を知りませんが、私たちはすでにwatch()関数で予測できない動作を扱っているので、もう少し不確実性は何ですか?自宅でフォローしている人にとっては、ファイルへのより迅速な追加により、ファイルの二重更新が停止するように見えますが、正直なところ、私にはよくわかりません。実際の場合、このソリューションの動作には満足しています。使用されます。これは、1秒に2回のように、最速で更新(コンテンツの置換)される1行のファイルです。

于 2015-09-26T06:36:33.637 に答える
0

1つ目は変更で、2つ目は名前変更です

リスナー機能との違いを生むことができます

function(event, filename) {

}

リスナーコールバックは2つの引数(イベント、ファイル名)を取得します。イベントは「名前の変更」または「変更」のいずれかであり、ファイル名はイベントをトリガーしたファイルの名前です。

// rm sourcefile targetfile
fs.watch( sourcefile_dir , function(event, targetfile)){
    console.log( targetfile, 'is', event)
}

ソースファイルの名前がターゲットファイルに変更されると、事実として3つのイベントが呼び出されます

null is rename // sourcefile not exist again
targetfile is rename
targetfile is change

これら3つのevnetをすべてキャッチしたい場合は、sourcefileのディレクトリを監視してください。

于 2013-01-21T02:26:25.507 に答える
0

Watchイベントの複数の登録を取得して、Watchイベントを数回発生させることがあります。監視ファイルのリストを保持し、ファイルがすでにリストにある場合はイベントの登録を回避することで、これを解決しました。

 var watchfiles = {};

function initwatch(fn, callback) {
    if watchlist[fn] {
        watchlist[fn] = true;
        fs.watch(fn).on('change', callback);
    }
}

.....。

于 2014-01-23T22:15:47.373 に答える
0

類似/同じ問題。画像がディレクトリに追加されたときに、画像を処理する必要がありました。これが私が二重発射に対処した方法です:

var fs = require('fs');
var working = false;

fs.watch('directory', function (event, filename) {
  if (filename && event == 'change' && active == false) {
    active = true;

    //do stuff to the new file added

    active = false;
});

新しいファイルとの関係が終了するまで、2回目の起動は無視されます。

于 2015-07-13T03:23:50.820 に答える
0

他の人の答えが言うように...これは多くの問題を抱えていますが、私はこれをこのように扱うことができます:

var folder = "/folder/path/";

var active = true; // flag control

fs.watch(folder, function (event, filename) {
    if(event === 'rename' && active) { //you can remove this "check" event
        active = false;

        // ... its just an example
        for (var i = 0; i < 100; i++) {
            console.log(i);
        }

        // ... other stuffs and delete the file
        if(!active){
            try {
                fs.unlinkSync(folder + filename);
            } catch(err) {
                console.log(err);
            }
            active = true
        }
    }
});

私があなたを助けることができることを願っています...

于 2016-02-04T14:18:14.290 に答える
0

最も簡単な解決策:

const watch = (path, opt, fn) => {
  var lock = false
  fs.watch(path, opt, function () {
    if (!lock) {
      lock = true
      fn()
      setTimeout(() => lock = false, 1000)
    }
  })
}
watch('/path', { interval: 500 }, function () {
  // ...
})
于 2017-11-25T00:02:00.660 に答える
0

puppeteerでファイルをダウンロードしていて、ファイルが保存されると、自動メールを送信していました。上記の問題により、2通のメールを送信していることに気づきました。を使用してアプリケーションを停止し、process.exit()pm2で自動起動することで解決しました。コードでフラグを使用しても、私は救われませんでした。

将来誰かがこの問題を抱えている場合は、この解決策を使用することもできます。プログラムを終了し、モニターツールで自動的に再起動します。

于 2020-03-09T10:11:58.887 に答える
0

これが私の簡単な解決策です。それは毎回うまく機能します。

// Update obj as file updates
obj = JSON.parse(fs.readFileSync('./file.json', 'utf-8'));
fs.watch('./file.json', () => {
  const data = JSON.parse(fs.readFileSync('./file.json', 'utf-8') || '{}');
  if(Object.entries(data).length > 0) { // This checks fs.watch() isn't false-firing
    obj = data;
    console.log('File actually changed: ', obj)
  }
});
于 2021-02-09T02:53:12.557 に答える
0

私は同じ問題に遭遇しました。複数回トリガーしたくない場合は、デバウンス機能を使用できます。

 fs.watch( 'example.xml', _.debounce(function ( curr, prev ) {
   // on file change we can read the new xml
   fs.readFile( 'example.xml','utf8', function ( err, data ) {
     if ( err ) throw err;
     console.dir(data);
     console.log('Done');
   });
 }, 100));
于 2021-12-12T15:43:16.737 に答える
0

オブザーバーのデバウンス

私が到達した解決策は、(a)問題の問題の回避策が必要であり、(b)複数の迅速なCtrl+sアクションが競合状態を引き起こさないようにするための解決策が必要であるということでした。これが私が持っているものです...

./**/utilities.js(どこか)
export default {
    ...
    debounce(fn, delay) {  // #thxRemySharp https://remysharp.com/2010/07/21/throttling-function-calls/
        var timer = null;
        
        return function execute(...args) {
            var context = this;
            clearTimeout(timer);
            timer = setTimeout(fn.bind(context, ...args), delay);
        };
    },
    ...
};
./**/file.js(他の場所)
import utilities from './**/utilities.js';  // somewhere
...
function watch(server) {
    const debounced = utilities.debounce(observeFilesystem.bind(this, server), 1000 * 0.25);
    const observers = new Set()
        .add( fs.watch('./src', debounced) )
        .add( fs.watch('./index.html', debounced) )
        ;
    console.log(`watching... (${observers.size})`);
    
    return observers;
}
    
function observeFilesystem(server, type, filename) {
    if (!filename) console.warn(`Tranfer Dev Therver: filesystem observation made without filename for type ${type}`);
    console.log(`Filesystem event occurred:`, type, filename);
    server.close(handleClose);
}
...

このように、私たちが渡すオブザベーションハンドラーfs.watchは[この場合はバインドされたバンクション]であり、複数の呼び出しが互いに数秒(250ms)未満で行われるとデバウンスされます。1000 * 0.25

Promiseコードが他のコールバックも利用するため、他のタイプの競合状態を回避するために、sのパイプラインも考案したことは注目に値するかもしれません。また、デバウンス機能が長年にわたって非常に有用であることが繰り返し証明されているRemySharpの帰属にも注意してください。

于 2022-02-24T03:45:29.037 に答える