如何使用 return 承诺的 NAPI 创建异步函数
How to create async function using NAPI that return Promises
我正在尝试使用 NAPI 创建节点模块。我必须创建 returns 承诺的异步函数。我不希望 testasynfunction 会阻塞 NodeJS 事件循环。 do_something_asynchronous 是一个同步函数。
napi_deferred do_something_synchronous(napi_env env,napi_deferred deferred){
printf("\n3) Function called");
//napi_deferred deferred;
napi_value undefined;
napi_status status;
// Create a value with which to conclude the deferred.
status = napi_get_undefined(env, &undefined);
if (status != napi_ok) return NULL;
sleep(5);
// Resolve or reject the promise associated with the deferred depending on
// whether the asynchronous action succeeded.
if (false) {
printf("\n5) Success\nXXXXXXX");
status = napi_resolve_deferred(env, deferred, undefined);
} else {
printf("\nReject");
status = napi_reject_deferred(env, deferred, undefined);
}
if (status != napi_ok) return NULL;
// At this point the deferred has been freed, so we should assign NULL to it.
deferred = NULL;
}
//Function will be called from the js
napi_value testasynfunction(napi_env env, napi_callback_info info){
printf("XXXXX Hello \n");
napi_deferred deferred;
napi_value promise;
napi_status status;
// Create the promise.
status = napi_create_promise(env, &deferred, &promise);
if (status != napi_ok) return NULL;
printf("\n1) Calling function to do something");
do_something_synchronous(env,deferred);
//std::async(do_something_asynchronous,env,deferred);
printf("\n2) Returning Promise");
return promise;
}
napi_property_descriptor testasync = DECLARE_NAPI_METHOD("testasyn", testasynfunction);
status = napi_define_properties(env, exports, 1, &testasync);
assert(status == napi_ok);
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
问题:
1) 我怎样才能 运行 do_something_synchronous 异步,这样 nodejs 事件循环就不会被阻塞和 return 承诺?
下面的代码片段是这个异步操作的关键组成部分。
napi_create_async_work() 函数分配一个工作对象,我们可以在其中指定工作处理程序函数,比如在我们的例子中 ExecuteMyPromise1() ( long 运行 或进程繁重的任务可以用它来部署)。 此函数将排队等待工作池线程并且它将与node.js主事件循环线程并行异步执行。
到目前为止一切正常,当 ExecuteMyPromise1 函数计划直接从工作线程与 JavaScript 层交换结果时就会出现问题。 任何 JavaScript 操作通常只能从本机插件的主线程调用 。然后对于这个结果交换,我们必须使用另一个将从主线程调用的本机函数。这就是我们使用 CompleteMyPromise1 函数处理程序的原因(如果任何最终清理 activity 也是从该函数完成的)。当异步逻辑完成或取消时,将从主事件循环线程调用此本机函数。
// The function called by javascript to get a promise returned.
napi_value MyPromise1(napi_env env, napi_callback_info info)
{
// -- -- -- --
// -- -- -- --
// Create a promise object.
status = napi_create_promise(env, &promDataEx->deferred, &promise);
if (status != napi_ok)
{
napi_throw_error(env, NULL, "Unable to create promise.");
}
// -- -- -- --
// -- -- -- --
{
// Create the async function.
napi_value resource_name;
napi_create_string_utf8(env, "MyPromise1", -1, &resource_name);
napi_create_async_work(env, NULL, resource_name,
ExecuteMyPromise1, CompleteMyPromise1,
promDataEx, &promDataEx->work);
napi_queue_async_work(env, promDataEx->work);
}
return promise;
}
// Execute the asynchronous work.
void ExecuteMyPromise1(napi_env env, void *data)
{
prom_data_ex_t *promDataEx = (prom_data_ex_t *)data;
// Calculate prime count
promDataEx->PrimeCount = CPrimeCount( promDataEx->x, promDataEx->y );
// Set the status as asynchronous_action is success
promDataEx->asynchronous_action_status = 0;
//sleep(3);
}
// Handle the completion of the asynchronous work.
void CompleteMyPromise1(napi_env env, napi_status status, void *data)
{
napi_value rcValue;
prom_data_ex_t *promDataEx = (prom_data_ex_t *)data;
napi_create_int32(env, promDataEx->PrimeCount, &rcValue);
// Resolve or reject the promise associated with the deferred depending on
// whether the asynchronous action succeeded.
if ( promDataEx->asynchronous_action_status == 0) // Success
{
status = napi_resolve_deferred(env, promDataEx->deferred, rcValue);
}
else
{
napi_value undefined;
status = napi_get_undefined(env, &undefined);
status = napi_reject_deferred(env, promDataEx->deferred, undefined );
}
if (status != napi_ok)
{
napi_throw_error(env, NULL, "Unable to create promise result.");
}
napi_delete_async_work(env, promDataEx->work);
free(promDataEx);
}
这是它的完整示例代码
https://github.com/msatyan/MyNodeC/blob/master/src/mync1/MyPromise1.cpp
JavaScrip 调用是 TestPromiseWithAsync()
https://github.com/msatyan/MyNodeC/blob/master/test/TestExtensions.js
我正在尝试使用 NAPI 创建节点模块。我必须创建 returns 承诺的异步函数。我不希望 testasynfunction 会阻塞 NodeJS 事件循环。 do_something_asynchronous 是一个同步函数。
napi_deferred do_something_synchronous(napi_env env,napi_deferred deferred){
printf("\n3) Function called");
//napi_deferred deferred;
napi_value undefined;
napi_status status;
// Create a value with which to conclude the deferred.
status = napi_get_undefined(env, &undefined);
if (status != napi_ok) return NULL;
sleep(5);
// Resolve or reject the promise associated with the deferred depending on
// whether the asynchronous action succeeded.
if (false) {
printf("\n5) Success\nXXXXXXX");
status = napi_resolve_deferred(env, deferred, undefined);
} else {
printf("\nReject");
status = napi_reject_deferred(env, deferred, undefined);
}
if (status != napi_ok) return NULL;
// At this point the deferred has been freed, so we should assign NULL to it.
deferred = NULL;
}
//Function will be called from the js
napi_value testasynfunction(napi_env env, napi_callback_info info){
printf("XXXXX Hello \n");
napi_deferred deferred;
napi_value promise;
napi_status status;
// Create the promise.
status = napi_create_promise(env, &deferred, &promise);
if (status != napi_ok) return NULL;
printf("\n1) Calling function to do something");
do_something_synchronous(env,deferred);
//std::async(do_something_asynchronous,env,deferred);
printf("\n2) Returning Promise");
return promise;
}
napi_property_descriptor testasync = DECLARE_NAPI_METHOD("testasyn", testasynfunction);
status = napi_define_properties(env, exports, 1, &testasync);
assert(status == napi_ok);
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
问题: 1) 我怎样才能 运行 do_something_synchronous 异步,这样 nodejs 事件循环就不会被阻塞和 return 承诺?
下面的代码片段是这个异步操作的关键组成部分。 napi_create_async_work() 函数分配一个工作对象,我们可以在其中指定工作处理程序函数,比如在我们的例子中 ExecuteMyPromise1() ( long 运行 或进程繁重的任务可以用它来部署)。 此函数将排队等待工作池线程并且它将与node.js主事件循环线程并行异步执行。
到目前为止一切正常,当 ExecuteMyPromise1 函数计划直接从工作线程与 JavaScript 层交换结果时就会出现问题。 任何 JavaScript 操作通常只能从本机插件的主线程调用 。然后对于这个结果交换,我们必须使用另一个将从主线程调用的本机函数。这就是我们使用 CompleteMyPromise1 函数处理程序的原因(如果任何最终清理 activity 也是从该函数完成的)。当异步逻辑完成或取消时,将从主事件循环线程调用此本机函数。
// The function called by javascript to get a promise returned.
napi_value MyPromise1(napi_env env, napi_callback_info info)
{
// -- -- -- --
// -- -- -- --
// Create a promise object.
status = napi_create_promise(env, &promDataEx->deferred, &promise);
if (status != napi_ok)
{
napi_throw_error(env, NULL, "Unable to create promise.");
}
// -- -- -- --
// -- -- -- --
{
// Create the async function.
napi_value resource_name;
napi_create_string_utf8(env, "MyPromise1", -1, &resource_name);
napi_create_async_work(env, NULL, resource_name,
ExecuteMyPromise1, CompleteMyPromise1,
promDataEx, &promDataEx->work);
napi_queue_async_work(env, promDataEx->work);
}
return promise;
}
// Execute the asynchronous work.
void ExecuteMyPromise1(napi_env env, void *data)
{
prom_data_ex_t *promDataEx = (prom_data_ex_t *)data;
// Calculate prime count
promDataEx->PrimeCount = CPrimeCount( promDataEx->x, promDataEx->y );
// Set the status as asynchronous_action is success
promDataEx->asynchronous_action_status = 0;
//sleep(3);
}
// Handle the completion of the asynchronous work.
void CompleteMyPromise1(napi_env env, napi_status status, void *data)
{
napi_value rcValue;
prom_data_ex_t *promDataEx = (prom_data_ex_t *)data;
napi_create_int32(env, promDataEx->PrimeCount, &rcValue);
// Resolve or reject the promise associated with the deferred depending on
// whether the asynchronous action succeeded.
if ( promDataEx->asynchronous_action_status == 0) // Success
{
status = napi_resolve_deferred(env, promDataEx->deferred, rcValue);
}
else
{
napi_value undefined;
status = napi_get_undefined(env, &undefined);
status = napi_reject_deferred(env, promDataEx->deferred, undefined );
}
if (status != napi_ok)
{
napi_throw_error(env, NULL, "Unable to create promise result.");
}
napi_delete_async_work(env, promDataEx->work);
free(promDataEx);
}
这是它的完整示例代码 https://github.com/msatyan/MyNodeC/blob/master/src/mync1/MyPromise1.cpp
JavaScrip 调用是 TestPromiseWithAsync() https://github.com/msatyan/MyNodeC/blob/master/test/TestExtensions.js