我在文件系统库中看到了很多同步函数,例如fs.readFileSync(filename, [options])
。
如果node有异步/非阻塞IO并且没有休眠方法,为什么要实现这些同步函数?我是否可以使用相同的机制来实现其他同步函数?
我在文件系统库中看到了很多同步函数,例如fs.readFileSync(filename, [options])
。
如果node有异步/非阻塞IO并且没有休眠方法,为什么要实现这些同步函数?我是否可以使用相同的机制来实现其他同步函数?
fs.readFileSync()
实际上只是一个包装器,用于
fs.readSync()
函数。问题是fs.readSync()相对于fs.read()的实现方式是什么。如果你看一下这两个函数的实现,它们都利用了bindings模块。在这种情况下,它被初始化为
var binding = process.binding('fs').
并且电话通话
binding.read(fd, buffer, offset, length, position, wrapper);//async
var r = binding.read(fd, buffer, offset, length, position);//sync
分别地,一旦我们处于“binding”模块中,我们就在v8,node_#####.cc领域之外。绑定('fs')的实现可以在node存储库代码中的node_file.cc中找到。Node引擎为C++调用提供重载,一个带回调,一个不带回调。node_file.cc代码利用了req_wrap类。这是v8引擎的包装器。在node_file.cc中,我们看到:
#define ASYNC_CALL(func, callback, ...) \
FSReqWrap* req_wrap = new FSReqWrap(#func); \
int r = uv_fs_##func(uv_default_loop(), &req_wrap->req_, \
__VA_ARGS__, After); \
req_wrap->object_->Set(oncomplete_sym, callback); \
req_wrap->Dispatched(); \
if (r < 0) { \
uv_fs_t* req = &req_wrap->req_; \
req->result = r; \
req->path = NULL; \
req->errorno = uv_last_error(uv_default_loop()).code; \
After(req); \
} \
return scope.Close(req_wrap->object_);
#define SYNC_CALL(func, path, ...) \
fs_req_wrap req_wrap; \
int result = uv_fs_##func(uv_default_loop(), &req_wrap.req, __VA_ARGS__, NULL); \
if (result < 0) { \
int code = uv_last_error(uv_default_loop()).code; \
return ThrowException(UVException(code, #func, "", path)); \
}
需要注意的是SYNC_CALL使用了不同的req-wrap。这是ASYNC方法中相关的req_wrap构造函数的代码,可以在req_wrap.h中找到。
ReqWrap() {
v8::HandleScope scope;
object_ = v8::Persistent<v8::Object>::New(v8::Object::New());
v8::Local<v8::Value> domain = v8::Context::GetCurrent()
->Global()
->Get(process_symbol)
->ToObject()
->Get(domain_symbol);
if (!domain->IsUndefined()) {
// fprintf(stderr, "setting domain on ReqWrap\n");
object_->Set(domain_symbol, domain);
}
ngx_queue_insert_tail(&req_wrap_queue, &req_wrap_queue_);
}
请注意,此函数会创建一个新的v8作用域对象来处理该事件的运行。这就是异步部分发生的地方。v8引擎启动一个新的JavaScript解释环境来单独处理这个调用。简而言之,如果您不构建/修改自己的Node版本,则无法实现自己的异步/同步调用版本,就像Node一样。话虽如此,异步真正适用于I/O操作。也许需要说明一下为什么您认为需要更多同步的原因。总的来说,如果您认为Node不支持您想要做的事情,那么您只是没有充分利用回调机制。