Skip to content

Instantly share code, notes, and snippets.

@bellbind
Last active January 10, 2022 17:47
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save bellbind/b69c3aa266cffe43940c to your computer and use it in GitHub Desktop.
Save bellbind/b69c3aa266cffe43940c to your computer and use it in GitHub Desktop.
[nodejs]Native module with libuv and v8::Promise on node-4

Native Module with libuv and Promise

  • v8::Persistent: Keep a v8 Object over scope
    • it require to release the Object manulally with Reset(void)
    • Use Object with convert Local to v8::Local<T>::New(isolate, persistent)
  • v8::Promise is made from v8::Promise::Resolver object
    • Promise::Resolver::New(isolate) then resolver->GetPromise()
    • use ressolver->Resolve(obj) or resolver->Reject(obj) to pass promise
  • v8::Isolate: requires to create v8 Object
    • hidden by Nan::New inside to use v8::Isolate::GetCurrent()
    • (for creating Isolate as barrier (e.f. for different tasks))
  • Nan::HandleScope scope: It requires to create v8 Object in outside of NAN_METHOD function (e.g. in native callbacks)
  • libuv pattern
    • make uv_xxx_t handle
    • set handle->data to objects use inside callback
    • call uv_xxx_init(uv_default_loop(), handle)
    • call uv_xxx_yyy(handle, callback, ...) function
    • in callback
      • retrieve objects from handle->data
      • uv_close(handle, dispose) to register deleting handle memory
      • do something as callback

Reference

For native module basics, see:

For APIs, see:

# -*- mode: python -*-
{
"targets": [
{
"include_dirs": ["<!(node -e \"require('nan')\")"],
"target_name": "TimerAndPromise",
"sources": [
"timer-and-promise.cc"
],
"conditions": [
["OS != 'win'",{
"cflags": ["-Wall", "-Wextra", "-pedantic"],
"cflags_cc": ["-std=c++14"],
}]
],
},
],
}
{
"name": "timer-and-promise",
"version": "0.1.0",
"description": "Native module example with libuv uv_timer and promise",
"license": "MIT",
"repository": "gist:",
"engine": {"node": ">=4.0.0"},
"main": "./build/Release/TimerAndPromise",
"dependencies": {
"nan": ">=2.0.0"
}
}
"use strict";
let m = require(".");
let start = Date.now();
m.wait(500).then((msg) => console.log(`${Date.now() - start}ms OK: ${msg}`));
// build: npm install
#include <iostream>
#include <nan.h>
// Promise returned function
NAN_METHOD(Wait) {
using ResolverPersistent = Nan::Persistent<v8::Promise::Resolver>;
auto ms = Nan::To<unsigned>(info[0]).FromJust();
auto resolver = v8::Promise::Resolver::New(info.GetIsolate());
auto promise = resolver->GetPromise();
auto persistent = new ResolverPersistent(resolver);
uv_timer_t* handle = new uv_timer_t;
handle->data = persistent;
uv_timer_init(uv_default_loop(), handle);
// use capture-less lambda for c-callback
auto timercb = [](uv_timer_t* handle) -> void {
Nan::HandleScope scope;
auto persistent = static_cast<ResolverPersistent*>(handle->data);
uv_timer_stop(handle);
uv_close(reinterpret_cast<uv_handle_t*>(handle),
[](uv_handle_t* handle) -> void {delete handle;});
auto resolver = Nan::New(*persistent);
resolver->Resolve(Nan::New("invoked").ToLocalChecked());
persistent->Reset();
delete persistent;
};
uv_timer_start(handle, timercb, ms, 0);
info.GetReturnValue().Set(promise);
}
NAN_MODULE_INIT(InitAll) {
Nan::Export(target, "wait", Wait);
}
NODE_MODULE(TimerAndPromise, InitAll)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment