简体   繁体   English

如何使用返回 Promises 的 NAPI 创建异步 function

[英]How to create async function using NAPI that return Promises

i am trying to create node module using NAPI.I have to create async function that returns promises.我正在尝试使用 NAPI 创建节点模块。我必须创建返回承诺的异步 function。 I don't want that testasynfunction will block NodeJS event loop.我不希望 testasynfunction 会阻塞 NodeJS 事件循环。 do_something_asynchronous is a synchronous function. do_something_asynchronous 是一个同步 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)

Question: 1) How can i run do_something_synchronous in asynchronously so that nodejs event loop will not get blocked and return promises?问题:1)我怎样才能异步运行 do_something_synchronous 以便 nodejs 事件循环不会被阻塞并返回承诺?

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). napi_create_async_work () function 分配一个工作 object ,我们可以在其中指定工作处理程序 function,例如在我们的情况下(长时间运行或部署繁重的任务)。 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 .这个 function 将成为工作池线程的队列,它将与 node.js 主事件循环线程并行异步执行

So far all looks OK, the problem will come when ExecuteMyPromise1 function plan to exchange result with JavaScript layer directly from the worker thread.到目前为止一切正常,当 ExecuteMyPromise1 function 计划直接从工作线程与 JavaScript 层交换结果时,问题就会出现。 Any JavaScript operation can normally only be called from a native addon's main thread .任何 JavaScript 操作通常只能从本机插件的主线程调用 Then for this result exchange we have to use another native function that will be called from main thread.然后对于这个结果交换,我们必须使用另一个本机 function 将从主线程调用。 That is why we are using CompleteMyPromise1 function handler (if any final cleanup activity that also done from this function).这就是我们使用CompleteMyPromise1 function 处理程序的原因(如果任何最终清理活动也通过此函数完成)。 This native function will be called from the main event loop thread when the asynchronous logic is completed or is cancelled.当异步逻辑完成或取消时,将从主事件循环线程调用此原生 function。

// 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);
}

Here the full example code for it https://github.com/msatyan/MyNodeC/blob/master/src/mync1/MyPromise1.cpp这里是它的完整示例代码https://github.com/msatyan/MyNodeC/blob/master/src/mync1/MyPromise1.cpp

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM