实现 nodejs代码能够监听文件目录变化,C++扩展代码如下
#include <iostream>
#include <nan.h>
#include <map>
#include "../deps/efsw/include/efsw/efsw.hpp"
namespace __watch__ {
using v8::Array;
using v8::Local;
using v8::Value;
using v8::Isolate;
using v8::Context;
using namespace std;
#define Watch watch
#define AddWatch addWatch
#define HandleFileAction handleFileAction
#define GetLastErrorLog getLastErrorLog
efsw::FileWatcher* file_watcher;
struct AsyncArgs {
efsw::WatchID watch_id;
std::string dir;
std::string filename;
efsw::Action action;
std::string old_filename;
uv_async_t handle;
Nan::Callback* callback;
};
void OnAsyncClosed(uv_handle_t* handle)
{
uv_async_t* async = (uv_async_t*)handle;
AsyncArgs* data = (AsyncArgs*)async->data;
delete data;
}
void OnEvent(uv_async_t* handle)
{
printf("in OnEvent1\n");
Nan::HandleScope scope;
AsyncArgs* data = (AsyncArgs*)handle->data;
Local<Value> argv[] = {
Nan::New((int)data->watch_id),
Nan::New(data->dir.c_str()).ToLocalChecked(),
Nan::New(data->filename.c_str()).ToLocalChecked(),
Nan::New(data->action),
Nan::New(data->old_filename.c_str()).ToLocalChecked()
};
data->callback->Call(5, argv);
uv_close((uv_handle_t*)handle, OnAsyncClosed);
printf("in OnEvent2\n");
}
class UpdateListener : public efsw::FileWatchListener {
public:
UpdateListener(Nan::Callback* callback) :
callback(callback)
{
}
~UpdateListener()
{
Nan::HandleScope scope;
delete callback;
}
void HandleFileAction(
efsw::WatchID watchid,
const std::string& dir,
const std::string& filename,
efsw::Action action,
std::string old_filename)
{
printf("in HandleFileAction1\n");
AsyncArgs* args = new AsyncArgs();
args->watch_id = watchid;
args->dir = dir;
args->filename = filename;
args->action = action;
args->old_filename = old_filename;
args->callback = callback;
uv_async_init(uv_default_loop(), &args->handle, OnEvent);
args->handle.data = (void*)args;
// _sleep(3*1000);
int res = uv_async_send(&args->handle);
std::cout << res;
printf("\n");
printf("in HandleFileAction2\n");
}
private:
Nan::Callback* callback;
};
std::map<std::string, std::vector<UpdateListener*> > listeners;
NAN_METHOD(Watch)
{
if(info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction())
{
return Nan::ThrowError("Wrong argument");
}
Isolate* isolate = Isolate::GetCurrent();
Local<Context> context = isolate->GetCurrentContext();
Nan::Utf8String path(info[0]->ToString(context).ToLocalChecked());
Nan::Callback* callback = new Nan::Callback(info[1].As<v8::Function>());
UpdateListener* listener = new UpdateListener(callback);
listeners[*path].push_back(listener);
efsw::WatchID watch_id = file_watcher->AddWatch(*path, listener, true);
if(watch_id < 0)
{
return Nan::ThrowError(efsw::Errors::Log::GetLastErrorLog().c_str());
}
info.GetReturnValue().Set(Nan::New((int)watch_id));
}
NAN_MODULE_INIT(Init)
{
file_watcher = new efsw::FileWatcher();
file_watcher->Watch();
Nan::Export(target, "watch", Watch);
}
NODE_MODULE(watch, Init)
}
nodejs调用代码
const obj = require("./build/Release/watch");
const fs = require('fs');
console.log('obj',obj);
obj.watch('/tmp',function(){//监听/tmp目录变化,如果目录中文件改变则执行回调
debugger;
console.log('tmp is call....');
console.log(arguments);
});
function second()
{
// 写回文件
fs.writeFile("D:/tmp/1.txt", "777", 'utf8', (writeErr) => {
if (writeErr) {
return console.error(writeErr);
}
console.log('文件已修改');
});
}
setTimeout(second,2000);
function abc()
{
console.log("abc=================================");
}
setTimeout(abc,3000);//JS主线程退出了,则不会执行到第6行代码 这里延迟要大于上面setTimeout的延迟
// console.log("111111111111111111111111112");
// while(true){//这种JS主线程卡住了,无法回调
// }
// obj.watch('/tmp/sdfkjl',function(){
// console.log(arguments);
// });
//流程
//监听目录文件变化-->目录文件发生改变-->c++代码回调JS函数-->JS主线程执行回调函数(JS主线程退出或卡住则无法执行回调)
测试结果