-
Notifications
You must be signed in to change notification settings - Fork 506
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Promises with AsyncWorker do not resolve properly #541
Comments
I don't know if it's V8 acting up or if it conformant to the specs, if it is Node + libuv acting up, or something else, but the exposed promise API is marked as experimental, so I would guess something is fishy in V8. It might be fixed in later versions for all I know. The only workaround I know of for now is to kick the event loop into the next tick somehow. One way is to somehow call |
I have wandered deep into the Lands of Tick Kicking and discovered there's a way to run pending tasks in the current context without forcing a global tick kicking. In fact, I just grabbed a line from inside the promise->Resolve(Nan::GetCurrentContext(), Nan::New(value));
+ v8::Isolate::GetCurrent()->RunMicrotasks(); promise->Reject(Nan::GetCurrentContext(), Nan::New(ErrorMessage()).ToLocalChecked());
+ v8::Isolate::GetCurrent()->RunMicrotasks(); Not sure if I'm lucky or this is correct, but it passes the test as you can check cloning the gist on the OP. |
Ah, that seems like a very good option indeed. Much cleaner. On March 3, 2016 5:50:26 AM GMT+02:00, Ranieri Althoff [email protected] wrote:
|
Ah, this does not work with ES7 async/await transpiled by babel somehow and is not working on a more complex example. |
Anyone got a fix to this issue? its still happening to me. However I believe this is v8's responsibility to solve this not NAN, |
You have to trigger microtasks manually. I guess Nan could implement a helper for that |
while this is still a problem for me too, it does not appear to be a problem within the context of the Atom editor.. I was prototyping some parts on the command line and was encountering this exact issue. When I finally moved my changes over into my Atom package I was working on, I did not need the hack to manually run the micro-tasks. I wonder is Atom is doing different.. Or if they are already working around the issue... because it does indeed seem and sound like a V8 issue.. |
If possible, handle Promises on pure JS. That's what I did, but I still hope for a better solution on the metal. |
Any progress on this issue? I am using node v8.9.4, AsyncWorker with v8::Promise on mocha not working for me either. The |
@enobufs AFAIK nothing has advanced in that matter. I am using Promises on JS and passing the callbacks as arguments into C++ code instead, though I'd prefer a thinner JS layer. |
@ranisalt That's a bummer... The native promise seems to be working fine, so I guess something is missing here. Yeah, promisification at JS land seems to be the way to go at least for now. |
I've tried to fix deprecation warnings on diff --git a/src/argon2.cpp b/src/argon2.cpp
index b950e01..615cd3f 100644
--- a/src/argon2.cpp
+++ b/src/argon2.cpp
@@ -61,7 +61,7 @@ argon2_context make_context(char* buf, const std::string& plain,
class HashWorker final: public Nan::AsyncWorker {
public:
HashWorker(std::string plain, Options options) :
- Nan::AsyncWorker{nullptr},
+ Nan::AsyncWorker{nullptr, "argon2:HashWorker"},
plain{std::move(plain)},
options{std::move(options)}
{}
@@ -96,11 +96,15 @@ public:
{
Nan::HandleScope scope;
- v8::Local<v8::Value> argv[] = {
+ auto argv = new v8::Local<v8::Value>[1] {
Nan::CopyBuffer(output.data(), output.size()).ToLocalChecked()
};
- Nan::MakeCallback(GetFromPersistent(CONTEXT).As<v8::Object>(),
- GetFromPersistent(RESOLVE).As<v8::Function>(), 1, argv);
+ Nan::Callback(GetFromPersistent(RESOLVE).As<v8::Function>()).Call(
+ /*target =*/ GetFromPersistent(CONTEXT).As<v8::Object>(),
+ /*argc =*/ 1, /*argv =*/ argv,
+ /*async_resource =*/ async_resource);
}
void HandleErrorCallback() override
@@ -108,9 +112,15 @@ public:
Nan::HandleScope scope;
- v8::Local<v8::Value> argv[] = {Nan::New(ErrorMessage()).ToLocalChecked()};
- Nan::MakeCallback(GetFromPersistent(CONTEXT).As<v8::Object>(),
- GetFromPersistent(REJECT).As<v8::Function>(), 1, argv);
+ auto argv = new v8::Local<v8::Value>[1] {
+ v8::Exception::Error(Nan::New(ErrorMessage()).ToLocalChecked())
+ };
+ Nan::Callback(GetFromPersistent(REJECT).As<v8::Function>()).Call(
+ /*target =*/ GetFromPersistent(CONTEXT).As<v8::Object>(),
+ /*argc =*/ 1, /*argv =*/ argv,
+ /*async_resource =*/ async_resource);
}
-- It works as expected, but it's around 20% slower. Am I doing it right? |
Why do you allocate |
Because allocating on the stack causes destruction to happen before the callback is fired. IOW, I get segfaults. What do you suggest? |
I assumed that it would work, since nothing I can think of has changed in that regard and I also assumed that you were doing a valid comparison. Based on the diff, you did not previously heap allocate it, so then it means it was wrong before, right? First you call Callback::Call https://github.com/nodejs/nan/blob/master/nan.h#L1637-L1651 This calls Callback::Call_ https://github.com/nodejs/nan/blob/master/nan.h#L1674-L1685 which calls AsyncResource::runInAsyncScope https://github.com/nodejs/nan/blob/master/nan.h#L517-L528 which calls |
This little detail about When Googling, people find that they should use |
Node.js calls More specifically: any time JS land is entered or exited, pending microtasks (promises) and The one exception is when you use @kkoopa Anything left to do or can this be closed out? |
@bnoordhuis So what is the right way to call a JS function from C++? Because pretty much everywhere I see only |
@LubosD Use |
Nothing I can think of. Note that |
Okay, I'll close this then. |
I think that last conversation is not on the same scope as the issue. I asked specifically about promise resolving/rejecting, which seems not to work as a function internally but rather a Maybe there could be a wrapper around a promise resolver that flushes microtask queue or whatever? The gist code still does not work without some v8 stuff that can change. |
Not until nan drops support for Node.js < v4.x. |
Will it happen someday? Those versions have already EOLd long ago, and nan is one of the libraries that can help pushing forward. |
Undoubtedly. See discussion in #676. |
This is a followup of #539 since the discussion there went far away. I tried to isolate the problem where a promise resolver would not work correctly sometimes, and @julien-f reported in this issue the promise is not working properly when a timeout is set.
I created a minimal example with tests in this gist. Clone it, install it then test it and you'll see when promises are implemented with Nan the timeout expires.
From what I could understand from #539 it happens because setTimeout holds the tick until the timeout expires so the promise resolve or reject function only runs after the timeout expires and the next tick is kicked. From that gist, how should one proceed to fix this issue?
The text was updated successfully, but these errors were encountered: