答复缓慢,答复node.js

我是全新的node.js和,我觉得我做了一些不正确的事情,但我有一个更好的答案search,然后有其他语言出于某种原因。 基本上我使用一个包裹c ++插件的节点做一些工作,然后我想通过websocket发送它,然后再对其进行一些额外的parsing。 当额外的parsing是同步完成时,立即发送(如预期)。 当我在一个承诺(这是第三方模块为我所做的)承诺工作之后,调用完成的callback花费很长的时间。 喜欢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. 

someFunction的多次callback可能会在第一次调用someOtherFunction之前发生。 这些都是主事件循环发布的事件,所以我不相信任何东西都阻挡在那里。 输出:

 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. 

所以我的问题原来的想法是,当解决scheme被调用,然后立即调用callback。 但是这看起来并不像这样。 有什么东西是触发callback最终触发,但我不知道什么,它似乎是随机的,当它实际上。 任何帮助,将不胜感激!

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.... 

Promise .then()callback决不会立即调用resolve() 。 相反,它们总是被asynchronous调用。 这提供了统一的asynchronous行为,无论是同步还是asynchronous调用parsing,从而使调用者的生活变得轻松许多。

Promise等待,直到当前执行线程中的其他代码已经执行完毕,堆栈帧已经被清除回“平台代码”。 然后,调用.then()callback。 如果在执行线程中做了很多其他的事情,那么在调用.then()处理程序之前可能会有一段延迟。

我通过从本地v8 Promise切换到蓝鸟诺言解决了这个问题。 原生v8 Promise由Microtask队列处理,我不知道如何处理c ++插件(我永远不能得到一个好的堆栈跟踪看到),但它看起来像microtask队列变得饿死,直到它最终运行一定的事件后刷新它(仍然不确定)。 蓝鸟使用SetImmediate和它立即处理,为我解决了这个问题。

进一步阅读阅读: https : //github.com/nodejs/node-v0.x-archive/issues/7714

这是在v0.12“固定”,我实际上使用io.js v3.2.0。 我不是100%确定这是相同的问题还是不同的问题。 无论哪种方式,我现在坚持蓝鸟