title: how to implement node-nan callback using node-addon-api
body: <p>Until now I've only implemented synchronous node-addon-api methods, i.e., a JavaScript function makes a call, work is done, and the addon returns. I have big gaps in knowledge when it comes to the inner workings of v8, libuv, and node, so please correct any obvious misconceptions.</p>
  
  <p>The goal is to call a JavaScript callback when C++ garbage collection callbacks are called from v8. I originally just called the JavaScript callback from the v8 garbage collection callback but that ended up with a segv after a couple calls. It seems that just making a call into JavaScript while being called from a v8 callback has some problems (v8 docs the callbacks shouldn't allocate objects). So I looked around and found a Nan-based example that uses <code>libuv</code> and Nan's <code>AsyncResource</code> to make the callback. The following approach works using <code>node-nan</code>:</p>
  
  <pre><code>NAN_GC_CALLBACK(afterGC) {
      uint64_t et = uv_hrtime() - gcStartTime;
  
      // other bookkeeping for GCData_t raw.
  
      if (doCallbacks) {
          uv_async_t* async = new uv_async_t;
          GCData_t* data = new GCData_t;
  
          *data = raw;
          data-&gt;gcTime = et;
  
          async-&gt;data = data;
  
          uv_async_init(uv_default_loop(), async, asyncCB);
          uv_async_send(async);
      }
  }
  
  class GCResponseResource : public Nan::AsyncResource {
   public:
      GCResponseResource(Local&lt;Function&gt; callback_)
          : Nan::AsyncResource("nan:gcstats.DeferredCallback") {
      callback.Reset(callback_);
      }
  
      ~GCResponseResource() {
          callback.Reset();
      }
  
      Nan::Persistent&lt;Function&gt; callback;
  };
  
  static GCResponseResource* asyncResource;
  
  static void closeCB(uv_handle_t *handle) {
      delete handle;
  }
  
  static void asyncCB(uv_async_t *handle) {
      Nan::HandleScope scope;
      GCData_t* data = static_cast&lt;GCData_t*&gt;(handle-&gt;data);
  
      Local&lt;Object&gt; obj = Nan::New&lt;Object&gt;();
  
      Nan::Set(obj, Nan::New("gcCount").ToLocalChecked(),
          Nan::New&lt;Number&gt;((data-&gt;gcCount));
      Nan::Set(obj, Nan::New("gcTime").ToLocalChecked(),
          Nan::New&lt;Number&gt;(data-&gt;gcTime));
  
      Local&lt;Object&gt; counts = Nan::New&lt;v8::Object&gt;();
      for (int i = 0; i &lt; maxTypeCount; i++) {
          if (data-&gt;typeCounts[i] != 0) {
              Nan::Set(counts, i, Nan::New&lt;Number&gt;(data-&gt;typeCounts[i]));
          }
      }
      Nan::Set(obj, Nan::New("gcTypeCounts").ToLocalChecked(), counts);
  
      Local&lt;Value&gt; arguments[] = {obj};
      Local&lt;Function&gt; callback = Nan::New(asyncResource-&gt;callback);
      v8::Local&lt;v8::Object&gt; target = Nan::New&lt;v8::Object&gt;();
      asyncResource-&gt;runInAsyncScope(target, callback, 1, arguments);
      delete data;
      uv_close((uv_handle_t*) handle, closeCB);
  }
  </code></pre>
  
  <p>My question is how would I do this using the node-addon-api instead of nan?</p>
  
  <p>It's not clear to me what the node-addon-api equivalent of <code>uv_async_init</code>, <code>uv_async_send</code>, etc are. This is partially because it's not clear to me what underlying <code>N-API</code> (as opposed to <code>node-addon-api</code>) functions are required.</p>
  
  <p>I have been unable to find an example like this. The <a href="https://github.com/nodejs/node-addon-examples/blob/master/3_callbacks/node-addon-api/addon.cc" rel="nofollow noreferrer">callback example</a> is completely synchronous. The <a href="https://github.com/nodejs/node-addon-examples/tree/master/async_pi_estimate/node-addon-api" rel="nofollow noreferrer">async pi example</a> uses a worker thread to perform a task but that seems overkill compared to the approach in the nan-based code using the <code>uv</code> primitives.</p>