Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/markusjx/n-api-tools
A toolbox for node-addon-api
https://github.com/markusjx/n-api-tools
javascript n-api nodejs promise
Last synced: about 1 month ago
JSON representation
A toolbox for node-addon-api
- Host: GitHub
- URL: https://github.com/markusjx/n-api-tools
- Owner: MarkusJx
- License: mit
- Created: 2020-07-20T11:46:08.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2024-01-10T01:11:16.000Z (10 months ago)
- Last Synced: 2024-10-08T12:42:22.497Z (about 1 month ago)
- Topics: javascript, n-api, nodejs, promise
- Language: C++
- Homepage:
- Size: 189 KB
- Stars: 1
- Watchers: 2
- Forks: 1
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# n-api-tools
A toolbox containing C++ classes to be used with node-addon-api.## Installation
```sh
npm install @markusjx/n-api-tools
```## Usage
First, include the file in your project. CMake example:
```cmake
execute_process(COMMAND node -p "require('@markusjx/n-api-tools').include"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE N_API_TOOLS_DIR)# Include the directory
include_directories(${N_API_TOOLS_DIR})
```This library is header-only, just include it:
```c++
#include
```
### Promises
#### Void promises
```c++
Napi::Promise returnsPromise(const Napi::CallbackInfo &info) {
// Return a promise
return napi_tools::promises::promise(info.Env(), [] {
// Sleep to pretend we're actually doing work
std::this_thread::sleep_for(std::chrono::seconds(2));
});
}
```#### Non-void promises
Non-void promises support most basic types as numbers, strings, vectors or booleans.
```c++
Napi::Promise returnsPromise(const Napi::CallbackInfo &info) {
// Return a promise
return napi_tools::promises::promise(info.Env(), [] {
// Sleep to pretend we're actually doing work
std::this_thread::sleep_for(std::chrono::seconds(2));// Return a string value
return "some string";
});
}
```### Callbacks
Callbacks can be used to call javascript function even without supplying a ``Napi::Env``.
The ``napi_tools::callbacks::callback`` takes function-like template arguments,
e.g. ```` or ````
#### Void callbacks
Create a callback with no arguments:
```c++
// Create a void callback
napi_tools::callbacks::callback callback = nullptr;// Create a callback setter.
// This function should be exported and called by javascript.
// info[0] should be a Napi::Function.
void setCallback(const Napi::CallbackInfo &info) {
callback = callbacks::callback(info);
}// Call a callback function
void callCallback() {
// Call the function async
callback();
}
```Create a callback with arguments:
```c++
// Create a void callback with arguments
napi_tools::callbacks::callback callback = nullptr;// Create a callback setter.
// This function should be exported and called by javascript.
// info[0] should be a Napi::Function.
void setCallback(const Napi::CallbackInfo &info) {
callback = callbacks::callback(info);
}// Call a callback function
void callCallback() {
// Call the function async and supply some arguments
callback("some string", 42);
}
```### Non-void callbacks
Non-void callbacks return a ``std::promise`` to get a ``std::future``
from to get the result of the callback. **NOTE:** If you call ``std::future::wait()``
in the main thread, you will create a deadlock as the callback cannot be called since
the main thread is waiting for the callback to be called. To call a callback function
from node.js use a ``napi_tools::promises::Promise`` or some other technique to not
block the main thread. You can also supply a callback function to be called with the
function return type.Create a callback with no arguments:
```c++
// Create a callback returning a number
napi_tools::callbacks::callback callback = nullptr;// Create a callback setter.
// This function should be exported and called by javascript.
// info[0] should be a Napi::Function.
void setCallback(const Napi::CallbackInfo &info) {
callback = callbacks::callback(info);
}// Call a callback function.
void callCallback() {
// Call the function async. It returns a std::promise
std::promise promise = callback();// Get the future
std::future future = promise.get_future();// Wait for the future to be resolved and get the result
future.wait();
int res = future.get();
}
```Create a callback with no arguments and without ``std::future``:
```c++
// Create a callback returning a number
napi_tools::callbacks::callback callback = nullptr;// Create a callback setter.
// This function should be exported and called by javascript.
// info[0] should be a Napi::Function.
void setCallback(const Napi::CallbackInfo &info) {
callback = callbacks::callback(info);
}// Call a callback function.
void callCallback() {
// Call the callback and supply a callback function
callback([] (int res) {
// The lambde will be called when the callback function finished.
// The result of the callback will be stored in res.
});
}
```Create a callback with arguments:
```c++
// Create a callback returning a number
napi_tools::callbacks::callback callback = nullptr;// Create a callback setter.
// This function should be exported and called by javascript.
// info[0] should be a Napi::Function.
void setCallback(const Napi::CallbackInfo &info) {
callback = callbacks::callback(info);
}// Call a callback function.
void callCallback() {
// Call the function async. It returns a std::promise
std::shared_ptr> promise = callback("some string", 42);// Get the future
std::future future = promise->get_future();// Wait for the future to be resolved and get the result
future.wait();
int res = future.get();
}
```Create a callback with arguments and without ``std::future``:
```c++
// Create a callback returning a number
napi_tools::callbacks::callback callback = nullptr;// Create a callback setter.
// This function should be exported and called by javascript.
// info[0] should be a Napi::Function.
void setCallback(const Napi::CallbackInfo &info) {
callback = callbacks::callback(info);
}// Call a callback function.
void callCallback() {
// Call the function and supply a callback function
callback("some string", 42, [] (int res) {
// The result will be stored in res
});
}
```Create a callback and wait for the js function to finish:
```c++
// Create a callback returning a number
napi_tools::callbacks::callback callback = nullptr;// Create a callback setter.
// This function should be exported and called by javascript.
// info[0] should be a Napi::Function.
void setCallback(const Napi::CallbackInfo &info) {
callback = callbacks::callback(info);
}// Call a callback function.
void callCallback() {
// Call the sync version of the function
int result = callback.callSync("some string", 42);
}
```Supply a conversion function with the callback:
```c++
// Create a callback returning a number
napi_tools::callbacks::callback callback = nullptr;// Create a callback setter.
// This function should be exported and called by javascript.
// info[0] may be a Napi::Function.
void setCallback(const Napi::CallbackInfo &info) {
// Create a conversion function.
// The conversion function must return std::vector
const auto converter = [] (std::string, int) -> std::vector {
// Convert the values
};// Set the callback and set the environment and the function manually.
// Aditionally, supply the custom conversion function
callback = callbacks::callback(info.Env(),
info[0].As ints;// The toNapiValue function
static Napi::Value toNapiValue(const Napi::Env &env, const custom_class &c) {
Napi::Object obj = Napi::Object::New(env);// Convert the attributes using Napi::Value::From
obj.Set("s1", Napi::Value::From(env, c.s1));
obj.Set("s2", Napi::Value::From(env, c.s1));
obj.Set("i", Napi::Value::From(env, c.i));// You may also use the included conversion functions.
// These can handle most basic types as strings, integers,
// but also std::vector and std::map, plus classes with
// the toNapiValue and/or fromNapiValue function(s)
obj.Set("ints", napi_tools::util::conversions::cppValToValue(env, ints));
return obj;
}// The fromNapiValue function
static custom_class fromNapiValue(const Napi::Env &env, const Napi::Value &val) {
// Assuming val is an object, you may test if it actually is
Napi::Object obj = val.ToObject();// Set all values
custom_class c;
c.s1 = obj.Get("s1").ToString();
c.s2 = obj.Get("s2").ToString();
c.i = obj.Get("i").ToNumber();// napi_tools also has functions to convert from napi values:
c.ints = napi_tools::util::conversions::convertToCpp>(obj.Get("ints"));
return c;
}
};
```## Other tools
### Catch all exceptions
To catch all exceptions possibly thrown by c++ to throw them in the javascript process,
use the ``TRY``/``CATCH_EXCEPTIONS`` macros:
```c++
void someFunction(const Napi::CallbackInfo &info) {
TRY
// Some code that may throw an exception
CATCH_EXCEPTIONS
}
```### Check argument types
To check if the number of supplied arguments, and the argument types match,
use the ``CHECK_ARGS(...)`` macro. A ``Napi::Error`` will be thrown if
the arguments do not match. Supported type names are: ``string``, ``number``,
``function``, ``object``, ``boolean``, ``array``, ``buffer``, ``undefined``, ``null``.Example:
```c++
void someFunction(const Napi::CallbackInfo &info) {
using namespace napi_tools;
// Expect a function, a string, a number and a boolean
CHECK_ARGS(function, string, number, boolean);
}
```It is also possible to allow multiple types as an input:
```c++
void someFunction(const Napi::CallbackInfo &info) {
using namespace napi_tools;
// Expect a string, number, null or undefined
CHECK_ARGS(string | number | null | undefined);
}
```### Export functions
To make exporting functions in your ``ìnit`` method easier, n-api-tools provides the
``EXPORT_FUNCTION(exports, env, fn)`` macro. This macro will "export" functions using
their C++ function name to javascript.Example:
```c++
Napi::Object InitAll(Napi::Env env, Napi::Object exports) {
EXPORT_FUNCTION(exports, env, func1);
EXPORT_FUNCTION(exports, env, func2);
EXPORT_FUNCTION(exports, env, anotherFunc);return exports;
}// Initialize the module
NODE_API_MODULE(some_module, InitAll)
```