如何承诺 node.js 插件方法

How to promisify a node.js addon method

我想为 node-java NPM 包准备一个拉取请求以支持 Promises/A+。这个包利用 JNI 使得在 node.js 应用程序中使用来自 Java 脚本的 Java classes 成为可能。对于每个导入的 java class,它在同步和异步变体中公开 class 的方法。异步变体使用标准 node.js 回调函数,这些函数很容易从 java 脚本中承诺(我已经使用 Q 和 Bluebird 这样做了)。但我想增强 node-java 以便它可以自动提供 promisified 方法。对于已经使用过 v8 和 node.js 插件的人来说,这可能是一项微不足道的任务,但我是两者的新手。我希望这里有人可以节省我可能至少几天的学习曲线。

我需要修改的关键代码在 src/javaObject.cpp 中,看起来像这样(我添加了一些 github 上源代码中没有的注释):

for(std::list<jobject>::iterator it = methods.begin(); it != methods.end(); ++it) {
  jstring methodNameJava = (jstring)env->CallObjectMethod(*it, method_getName);
  assert(!env->ExceptionCheck());
  std::string methodNameStr = javaToString(env, methodNameJava);

  // Create the async method variant, named exactly as the java method is named
  v8::Handle<v8::String> methodName = NanNew<v8::String>(methodNameStr.c_str());
  v8::Local<v8::FunctionTemplate> methodCallTemplate = NanNew<v8::FunctionTemplate>(methodCall, methodName);
  funcTemplate->PrototypeTemplate()->Set(methodName, methodCallTemplate->GetFunction());

  // Create the sync method variant, with 'Sync' appended to the method name
  v8::Handle<v8::String> methodNameSync = NanNew<v8::String>((methodNameStr + "Sync").c_str());
  v8::Local<v8::FunctionTemplate> methodCallSyncTemplate = NanNew<v8::FunctionTemplate>(methodCallSync, methodName);
  funcTemplate->PrototypeTemplate()->Set(methodNameSync, methodCallSyncTemplate->GetFunction());
}

我想在初始化时将一个 promisify 函数(用 javascript 编写)传递给 node-java,如下所示:

var java = require('java');
var asyncOptions = {
  promisify: require('q').nfbind     // or require('bluebird').promisify
  suffix: 'Promise'
};
java.setAsyncOptions(asyncOptions);

我需要知道如何实现新方法 setAsyncOptions(asyncOptions);

然后,在上面的循环中,我将按照这些行添加代码:

// Create the promise method variant, appending to the original method name the passed in suffix.
v8::Handle<v8::String> promiseSuffixStr = ???; // asyncOptions.suffix
v8::Handle<v8::String> methodNamePromise = NanNew<v8::String>(methodNameStr + promiseSuffixStr);
v8::Local<v8::FunctionTemplate> methodCallTemplate = NanNew<v8::FunctionTemplate>(methodCall, methodName);
v8::Local<v8::FunctionTemplate> promiseCallTemplate = ???; // asyncOptions.promisify(methodCallTemplate)
funcTemplate->PrototypeTemplate()->Set(methodNamePromise, promiseCallTemplate->GetFunction());

我需要有关显示为 ??? 的两个部分的帮助。

在此先感谢您的帮助。


编辑:我在这方面取得了很好的进展,并提交了 PR 草案。 node-java 的所有者同意与我一起完成它。欢迎阅读本文的任何人查看 the PR。当我们有完整的解决方案时,我会用答案更新这个问题。

我找到了完整的解决方案,现在已合并到 node-java npm 包中。参见 PR187