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.
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);
}
Here the full example code for it
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