如何使用返回承诺的NAPI创建异步函数 [英] How to create async function using NAPI that return Promises

查看:249
本文介绍了如何使用返回承诺的NAPI创建异步函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用NAPI创建节点模块.我必须创建一个返回promise的异步函数.我不希望testasynfunction会阻止NodeJS事件循环.do_something_asynchronous是一个同步函数.

i am trying to create node module using NAPI .I have to create async function that returns promises. I don't want that testasynfunction will block NodeJS event loop. do_something_asynchronous is a synchronous function.

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事件循环不会被阻塞并返回诺言?

Question : 1) How can i run do_something_synchronous in asynchronously so that nodejs event loop will not get blocked and return promises ?

推荐答案

以下代码段是此异步操作的关键组件. napi_create_async_work()函数分配一个工作对象,我们可以在其中指定工作者处理程序函数,例如在我们的情况下 ExecuteMyPromise1 ()(可以使用以下命令部署长时间运行或处理繁重的任务:它).此函数将作为工作池线程的队列,并且它将与node.js主事件循环线程并行执行.

The following code snippet is the key component of this asynchronously operations. The napi_create_async_work() function allocates a work object where we can specify the worker handler function, say in our case ExecuteMyPromise1() (long running or process heavy task can be deployed with it). This function will be queue for worker pool thread and it will get executed asynchronously in parallel with the node.js main event loop thread.

到目前为止,一切看起来都不错,当ExecuteMyPromise1函数计划直接从辅助线程与JavaScript层交换结果时,问题就会出现.通常只能从本机插件的主线程调用任何JavaScript操作.然后,为了进行结果交换,我们必须使用另一个将从主线程调用的本机函数.这就是为什么我们使用 CompleteMyPromise1 函数处理程序的原因(如果此功能也执行了任何最终的清理活动).当异步逻辑完成或取消时,将从主事件循环线程中调用此本地函数.

So far all looks OK, the problem will come when ExecuteMyPromise1 function plan to exchange result with JavaScript layer directly from the worker thread. Any JavaScript operation can normally only be called from a native addon's main thread. Then for this result exchange we have to use another native function that will be called from main thread. That is why we are using CompleteMyPromise1 function handler (if any final cleanup activity that also done from this function). This native function will be called from the main event loop thread when the asynchronous logic is completed or is cancelled.

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

Here the full example code for it https://github.com/msatyan/MyNodeC/blob/master/src/mync1/MyPromise1.cpp

JavaScrip调用为TestPromiseWithAsync() https://github.com/msatyan/MyNodeC/blob/master/test/TestExtensions.js

The JavaScrip call is TestPromiseWithAsync() https://github.com/msatyan/MyNodeC/blob/master/test/TestExtensions.js

这篇关于如何使用返回承诺的NAPI创建异步函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆