【发布时间】:2015-11-28 13:18:38
【问题描述】:
我是 node.js 的新手,我觉得我做错了什么,但由于某种原因,我很难在谷歌上搜索到好的答案,然后我会用其他语言搜索。基本上我正在使用一个节点包装的 c++ 插件来做一些工作,然后我想在对它进行一些额外的解析之后通过 websocket 发送它。当附加解析同步完成时,它会立即发送(如预期的那样)。当我在调用 resolve 后在 promise 中完成工作(这是第三方模块为我做的事情)时,调用已完成的回调需要很长时间。比如5-10秒以上。代码如下:
var addon = require('...'); // Node wrapped C++ module
...
var server = http.createServer(){...};
var ios = io.listen(server);
function someFunction(args) {
console.log("Preparing to call some function");
someOtherFunction(args).then(funtction(val) {
console.log("Sending val over websocket....");
ios.sockets.emit('thing', val);
}
}
function someOtherFunction(args) {
return new Promise(function(resolve, reject) {
//logic
resolve(someVal);
console.log("Done with someOtherFunc");
}
}
ios.sockets.on('connection', function(socket){
console.log("Conneced");
// This does some work on a different thread. Eventually reposts to event loop and calls callback
addon.doThing("someVal", someFunc);
socket.on('disconnect', function() {
console.log("Disconnected");
});
});
输出:
Connected
Preparing to call some function...
Done with someOtherFunc;
<variable delay sometimes up to 5-10 seconds>
Sending val over websocket.
在第一次调用 someOtherFunction 完成之前,可能会发生对 someFunction 的多次回调。这些都是发布到主事件循环的事件,所以我不相信那里有任何阻塞。 输出:
Connected
Preparing to call some function...
Done with someOtherFunc;
<1 second delay>
Preparing to call some function...
Done with someOtherFunc;
<1 second delay>
Preparing to call some function...
Done with someOtherFunc;
<1 second delay>
<variable delay sometimes up to 5-10 seconds>
Sending val over websocket.
Sending val over websocket.
Sending val over websocket.
所以我的问题最初的想法是,当调用 resolve 时,立即调用回调。但这看起来并没有发生。某些东西正在触发回调以最终触发,但我不知道是什么,而且它实际上是随机的。任何帮助将不胜感激!
C++ 插件代码:
class NodeWrapper {
public:
static NodeWrapper& GetInstance() {
static NodeWrapper mInstance;
return mInstance;
}
~NodeWrapper() {
uv_close((uv_handle_t*) &mNodeAsyncEventLoop, NULL);
};
static void SendToNode(uv_async_t *handle) {
GetInstance().SendToNode();
}
void SendToNode() {
uv_mutex_lock(&mMutex);
swap(pushQueue, popQueue);
uv_mutex_unlock(&mMutex);
while(!popQueue.empty()) {
Data* pData = popQueue.front();
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
const unsigned argc = 1;
Local<Value> argv = { node::Buffer::New(isolate, pData->mData, pData->mLen, DataDeleter, NULL).ToLocalChecked() };
Local<Function> cb = Local<Function>::New(isolate, mNodeCB);
cb->Call(isolate->GetCurrentContext()->Global(), argc, &argv);
popQueue.pop();
}
log << "Done with Callback!" << std::endl;
}
void SendOnData(const void* pData, DWORD dwLen) {
log << "Callback received!" << std::endl;
if(dwLen > 0) {
uv_mutex_lock(&mMutex);
pushQueue.push(new Data(pData, dwLen));
uv_mutex_unlock(&mMutex);
uv_async_send(&GetInstance().mNodeAsyncEventLoop);
}
};
static NodeWrapper mInstance;
UniquePersistent<Function> mNodeCB;
private:
NodeWrapper() {
uv_async_init(uv_default_loop(), &mNodeAsyncEventLoop, &NodeWrapper::SendToNode);
uv_mutex_init(&mMutex);
};
DATA_QUEUE pushQueue;
DATA_QUEUE popQueue;
uv_mutex_t mMutex;
uv_async_t mNodeAsyncEventLoop;
};
void doThing(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
auto f = std::bind(&NodeWrapper::SendOnData, &NodeWrapper::GetInstance());
DoThingAnotherThreadAndCallCallback(f);
NodeWrapper::GetInstance().mNodeCB = UniquePersistent<Function>(isolate, Local<Function>::Cast(args[1]));
}
输出更新:
22:01:57.831645 - Callback received
Preparing to call some function....
Done with someOtherFunc
22:01:57.839711 - Done with Callback!
22:01:57.918472 - Callback received
Preparing to call some function....
Done with someOtherFunc
22:01:57.927344 - Done with Callback!
Sending val over websocket....
Sending val over websocket....
【问题讨论】: