最近發生了不少事,node終於迎來了8.1.0的更新,同時rust語言也迎來了他的1.18版本,帶來了更多的更新。不過這裏主要想要敘述的仍是關於node的新特性napi。因爲找了下網上的教程基本都止步於官網的hello_world的demo的成功運行,因此想用本身淺薄的英語知識去啃一下深刻的東西。
javascript
因爲大部分的二進制node模塊都嚴重依賴於V8引擎的暴露的接口,一旦v8引擎有所變更,就會致使模塊的使用出現問題。因此按照程序員通用的思路,既然依賴太強,那就抽象一層吧,因此node官方作了這麼一層抽象,使程序員不用直接面對V8引擎,而是使用node抽象出來的一層接口,這樣保證了在各個版本之間模塊的通用性等等。嗯,這段話是小生本身寫的,不對之處請指出Orz。html
講道理,這段示例其實在各個文章中都大同小異,相信各個看官都看過好幾遍了,不過爲了文章的連貫性,小生仍是不得再也不寫一次。java
首先,咱們更新node到8.1.0或以上版本node
node --versionc++
而後咱們全局安裝node-gyp,小生用的yarn,因此就用yarn安裝了程序員
yarn global add node-gypes6
安裝成功後咱們新建一個文件夾來作實驗npm
mkdir napi
cd napi
yarn init -y json
yarn初始化項目的方式是init -y,npm是 init -f,不過這個其實沒啥子,主要是初始化package.json而已。而後咱們按照之前和之前寫二進制模塊同樣的方式,先創建src目錄,創建.cc文件,而後創建binding.gyp文件api
mkdir src
touch src/hello.cc
touch binding.gyp
而後咱們編輯hello.cc,這裏直接使用官方的demo了:
#include <node_api.h>
// 實際暴露的方法,這裏只是簡單返回一個字符串
napi_value HelloMethod (napi_env env, napi_callback_info info) {
napi_value world;
napi_create_string_utf8(env, "world", 5, &world);
return world;
}
// 擴展的初始化方法,其中
// env:環境變量
// exports、module:node模塊中對外暴露的對象
void Init (napi_env env, napi_value exports, napi_value module, void* priv) {
// napi_property_descriptor 爲結構體,做用是描述擴展暴露的 屬性/方法 的描述
napi_property_descriptor desc = { "hello", 0, HelloMethod, 0, 0, 0, napi_default, 0 };
napi_define_properties(env, exports, 1, &desc); // 定義暴露的方法
}
NAPI_MODULE(hello, Init); // 註冊擴展,擴展名叫作hello,Init爲擴展的初始化方法複製代碼
而後咱們編輯binding.gyp:
{
"targets": [
{
"target_name": "hello",
"sources": [ "./src/hello.cc" ]
}
]
}複製代碼
接下來直接:
node-gyp rebuild
就能夠看到本地多出了build文件夾,而且能夠發現編譯後的文件build/Release/hello.node,因此咱們能夠直接寫一個js文件測試咱們的demo是否成功了:
//index.js
var a=require('./build/Release/hello')
console.log(a.hello())複製代碼
運行
node --napi-modules index.js
後發現輸出world,即一切正常,咱們完成了一個二進制包的編寫。因爲目前napi還屬於新特性階段,因此運行時須要加上--napi-modules
參數。恩,大多數的文章就到此爲止了,不太小生仍是決定看看官方的api,深刻研究下。
因爲文檔很長,無法一次看完慢慢整理,因此小生一邊看文檔,一邊思索一邊測試一邊寫,內容可能會有一點小小的混亂,請見諒。napi文檔傳送門
因爲napi是新特性,因此在運行時請加上參數--napi-modules
,同時在cc文件中需加上#include <node_api.h>
頭部
napi_value result;
napi_status status = napi_get_element(e object, i, &result);
if (status != napi_ok) {
//do someting
}複製代碼
其中napi_ok就是napi_status的枚舉取值之一,表示操做成功
napi_extended_error_info是一個結構體,在調用函數不成功時存儲了較爲詳細的錯誤信息
napi_env表示一個上下文的變量
napi_value是對全部js的基本值的一個密閉封裝,簡單來講,就是表示一個基本值
napi_handle_scope,這是一個抽象類型,用於管理和修改在特定範圍內建立的對象的生命週期,使用napi_open_handle_scope將創建一個上下文環境使用napi_close_handle_scope將關閉這個上下文環境,在關閉這個上下文後,全部在其中聲明的引用都將被關閉。說的簡單點,就是相似於給包了一個大括弧,全部的let屬性聲明週期都只能在這內部。
napi_escapable_handle_scope是一個將特定範圍內聲明的值返回到父做用域的一個特殊類型
napi_ref是一個抽象類型,用於引用napi_value,讓用戶能管理js值的生命週期
napi_callback_info這是傳遞給回調函數的一個封裝的數據類型,能夠用於獲取有關調用時的上下文信息,也能夠用於設置回調函數的返回值
經過Napi暴露給用戶設置的回調函數指針,設置回調應該知足如下函數簽名:
typedef void (*napi_callback)(napi_env, napi_callback_info);
napi_async_execute_callback與napi_async_complete_callback兩者皆是與回調函數一塊兒運行的函數指針,函數簽名須要知足如下:
typedef void (napi_async_execute_callback)(napi_env env, void data);
typedef void (napi_async_complete_callback)(napi_env env,napi_status status,void data);
全部的napi函數都使用相同的錯誤處理函數,在調用以後會返回napi_status
,在不出錯正常時會返回napi_ok
,若是隻是拋出異常,則會返回napi_pending_exception
,在二者皆不是的狀況下須要使用napi_is_exception_pending
來判斷是否有異常被掛起。當有錯誤發生時,則須要使用函數napi_get_last_error_info,該函數會將錯誤信息填充到參數napi_extended_error_info中,函數簽名以下:
NAPI_EXTERN napi_status napi_get_last_error_info(napi_env env,const napi_extended_error_info** result);
調用後會返回該次調用的napi_status
,若是結果是napi_ok
,那麼result參數將會被填充成napi_extended_error_info結構體,該結構體以下:
typedef struct napi_extended_error_info {
const char error_message;
void engine_reserved;
uint32_t engine_error_code;
napi_status error_code;
};
在使用napi_is_exception_pending
肯定有異常掛起後,有兩種方式來處理異常。第一種,也是官方推薦的一種,就是簡單處理後直接返回,使代碼觸發js內的異常,交由js自行處理。第二種,是不推薦的,就是嘗試自行處理異常,可使用napi_get_and_clear_last_exception
來獲取以及清除異常。不過在檢索後,發現沒法處理該異常,能夠選擇[napi_throw] []來從新拋出該異常。
napi_throw
NODE_EXTERN napi_status napi_throw(napi_env env, napi_value error);
該函數返回一個js可接受的錯誤
napi_throw_error
NODE_EXTERN napi_status napi_throw_error(napi_env env, const char* msg);
該函數拋出一個純文本的錯誤信息
napi_throw_type_error
NODE_EXTERN napi_status napi_throw_type_error(napi_env env, const char* msg);
該函數拋出一個純文本的類型錯誤信息
napi_throw_range_error
NODE_EXTERN napi_status napi_throw_range_error(napi_env env, const char* msg);
該函數拋出一個純文本的RangeError
napi_is_error
NODE_EXTERN napi_status napi_is_error(napi_env env,napi_value value,bool* result);
該函數會檢查傳入的napi_value是不是一個錯誤對象
napi_create_error
NODE_EXTERN napi_status napi_create_error(napi_env env, const char* msg);
該函數會返回一個js純文本錯誤
napi_create_type_error
NODE_EXTERN napi_status napi_create_type_error(napi_env env, const char* msg);
該函數會返回一個js純文本類型錯誤
napi_create_range_error
NODE_EXTERN napi_status napi_create_range_error(napi_env env, const char* msg);
該函數會返回一個js純文本RangeError
napi_get_and_clear_last_exception
NAPI_EXTERN napi_status napi_get_and_clear_last_exception(napi_env env,napi_value* result);
這裏官方文檔應該是寫錯了,官方文檔函數描述是This API returns true if an exception is pending.
,很明顯,這個描述是錯的,從前文來看,該函數的效果應該是獲取最近的一次的句柄,而且清除異常
napi_is_exception_pending
NAPI_EXTERN napi_status napi_is_exception_pending(napi_env env, bool* result);
這裏官方的描述依舊是This API returns true if an exception is pending.
,不過這下就正常了,該函數會在有異常被掛起時返回true
因爲在napi中全部js相關的值都是一個不透明的分裝,默認生命週期是和全局一致的,有時候處於安全和性能的考慮,須要將一些值得生命週期限制在必定的範圍之內,此時就須要用到上文提到過得open_handle_scope和napi_close_handle_scope來建立和關閉一個上下文環境。示例:
for (int i = 0; i < 1000000; i++) {
napi_handle_scope scope;
napi_status status = napi_open_handle_scope(env, &scope);
if (status != napi_ok) {
break;
}
napi_value result;
status = napi_get_element(e object, i, &result);
if (status != napi_ok) {
break;
}
// do something with element
status = napi_close_handle_scope(env, scope);
if (status != napi_ok) {
break;
}
}複製代碼
此時,因爲限制了做用域,因此每一個result的生命週期都被限制在了單次循環以內。
在有些時候某些值得生命週期須要大於自己所在區域的週期時,能夠將他們放在 napi_open_escapable_handle_scope
與napi_close_escapable_handle_scope
這兩個函數之間,此間定義的值的生命週期將與父級的做用域的生命週期一致,而不侷限於自己的生命週期。
> NODE_EXTERN napi_status napi_open_handle_scope(napi_env env,napi_handle_scope* result);
> NODE_EXTERN napi_status napi_close_handle_scope(napi_env env,napi_handle_scope scope);
> NODE_EXTERN napi_status napi_open_escapable_handle_scope(napi_env env,napi_handle_scope* result);
> NODE_EXTERN napi_status napi_close_escapable_handle_scope(napi_env env,napi_handle_scope scope);
> NAPI_EXTERN napi_status napi_escape_handle(napi_env env,napi_escapable_handle_scope scope,napi_value escapee,napi_value* result);複製代碼
Napi的模塊註冊使用NAPI_MODULE(addon, Init)
方式來註冊,其中Init方法簽名以下:
void Init(napi_env env, napi_value exports, napi_value module, void* priv);
Napi建立了一系列的api來負責建立各類類型的JavaScript值。這系列api主要用於如下功能:
typedef enum {
// ES6 types (corresponds to typeof)
napi_undefined,
napi_null,
napi_boolean,
napi_number,
napi_string,
napi_symbol,
napi_object,
napi_function,
napi_external,
} napi_valuetype;複製代碼
typedef enum {
napi_int8_array,
napi_uint8_array,
napi_uint8_clamped_array,
napi_int16_array,
napi_uint16_array,
napi_int32_array,
napi_uint32_array,
napi_float32_array,
napi_float64_array,
} napi_typedarray_type;複製代碼
napi_create_array
napi_status napi_create_array(napi_env env, napi_value* result)
該函數返回一個JavaScript數組類型對應的napi值
napi_create_array_with_length
napi_status napi_create_array_with_length(napi_env env,size_t length,napi_value* result)
該函數返回特定長度的JavaScript數組類型對應的napi值,可是該函數不能保證在建立陣列時由VM預先分配內存,若是須要保證緩衝區必須是能夠經過c直接讀取或寫入的連續的內存,須要使用napi_create_external_arraybuffer
napi_create_arraybuffer
napi_status napi_create_arraybuffer(napi_env env,size_t byte_length,void* data,napi_value result)
napi_create_buffer
napi_status napi_create_buffer(napi_env env,size_t size,void* data,napi_value result)
napi_create_buffer_copy
napi_status napi_create_buffer_copy(napi_env env,size_t length,const void data,void** result_data,napi_value result)
napi_create_external
napi_status napi_create_external(napi_env env,void data,napi_finalize finalize_cb,void finalize_hint,napi_value* result)
napi_create_external_arraybuffer
napi_status napi_create_external_arraybuffer(napi_env env,void external_data,size_t byte_length,napi_finalize finalize_cb,void finalize_hint,napi_value* result)
napi_create_external_buffer
napi_status napi_create_external_buffer(napi_env env,size_t length,void data,napi_finalize finalize_cb,void finalize_hint,napi_value* result)
napi_create_function
napi_status napi_create_function(napi_env env,const char utf8name,napi_callback cb,void data,napi_value* result)
該函數返回JavaScript中函數對應的napi值,用於包裝本地函數,使JavaScript能夠調用它
napi_create_object
napi_status napi_create_object(napi_env env, napi_value* result)
該函數返回一個默認的JavaScript對象,等同於在JavaScript中調用new Object()
napi_create_symbol
api_status napi_create_symbol(napi_env env,const char description,napi_value result)
napi_create_typedarray
napi_status napi_create_typedarray(napi_env env,napi_typedarray_type type,size_t length,napi_value arraybuffer,size_t byte_offset,napi_value* result)
napi_create_number
napi_status napi_create_number(napi_env env, double value, napi_value* result)
napi_create_string_utf16
napi_status napi_create_string_utf16(napi_env env,const char16_t str,size_t length,napi_value result)
napi_create_string_utf8
napi_status napi_create_string_utf8(napi_env env,const char str,size_t length,napi_value result)
napi_get_array_length
napi_status napi_get_array_length(napi_env env,napi_value value,uint32_t* result)
napi_get_arraybuffer_info
napi_status napi_get_arraybuffer_info(napi_env env,napi_value arraybuffer,void* data,size_t byte_length)
napi_get_buffer_info
napi_status napi_get_buffer_info(napi_env env,napi_value value,void* data,size_t length)
napi_get_prototype
napi_status napi_get_prototype(napi_env env,napi_value object,napi_value* result)
napi_get_typedarray_info
napi_status napi_get_typedarray_info(napi_env env,napi_value typedarray,napi_typedarray_type type,size_t length,void* data,napi_value arraybuffer,size_t* byte_offset)
napi_get_value_bool
napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result)
napi_get_value_double
napi_status napi_get_value_double(napi_env env,napi_value value,double* result)
napi_get_value_external
napi_status napi_get_value_external(napi_env env,napi_value value,void** result)
napi_get_value_int32
napi_status napi_get_value_int32(napi_env env,napi_value value,int32_t* result)
napi_get_value_int64
napi_status napi_get_value_int64(napi_env env,napi_value value,int64_t* result)
napi_get_value_string_length
napi_status napi_get_value_string_length(napi_env env,napi_value value,int* result)
napi_get_value_string_utf8
napi_status napi_get_value_string_utf8(napi_env env,napi_value value,char buf,size_t bufsize,size_t result)
napi_get_value_string_utf16
napi_status napi_get_value_string_utf16(napi_env env,napi_value value,char16_t buf,size_t bufsize,size_t result)
napi_get_value_uint32
napi_status napi_get_value_uint32(napi_env env,napi_value value,uint32_t* result)
napi_get_boolean
napi_status napi_get_boolean(napi_env env, bool value, napi_value* result)
napi_get_global
napi_status napi_get_global(napi_env env, napi_value* result)
napi_get_null
napi_status napi_get_null(napi_env env, napi_value* result)
napi_get_undefined
napi_status napi_get_undefined(napi_env env, napi_value* result)
napi_coerce_to_bool
napi_status napi_coerce_to_bool(napi_env env,napi_value value,napi_value* result)
對於JavaScript中的ToBoolean操做的一個實現
napi_coerce_to_number
napi_status napi_coerce_to_number(napi_env env,napi_value value,napi_value* result)
對於JavaScript中的ToNumber操做的一個實現
napi_coerce_to_object
napi_status napi_coerce_to_object(napi_env env,napi_value value,napi_value* result)
對於JavaScript中的ToObject操做的一個實現
napi_coerce_to_string
napi_status napi_coerce_to_string(napi_env env,napi_value value,napi_value* result)
對於JavaScript中的ToString操做的一個實現
napi_typeof
napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype* result)
對於JavaScript中的typeof操做的一個實現
napi_instanceof
napi_status napi_instanceof(napi_env env,napi_value object,napi_value constructor,bool* result)
對於JavaScript中的instanceof操做的一個實現
napi_is_array
napi_status napi_is_array(napi_env env, napi_value value, bool* result)
對於JavaScript中的isArrat函數的一個實現
napi_is_arraybuffer
napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result)
napi_is_buffer
napi_status napi_is_buffer(napi_env env, napi_value value, bool* result)
napi_is_error
napi_status napi_is_error(napi_env env, napi_value value, bool* result)
napi_is_typedarray
napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result)
napi_strict_equals
napi_status napi_strict_equals(napi_env env,napi_value lhs,napi_value rhs,bool* result)
比較傳入的左值和右值是否嚴格相等
在JavaScript中,屬性通常爲鍵和值的元組,napi中全部屬性鍵均可以用一下形式表示:
好比以下JavaScript代碼:
const obj = {};
obj.myProp = 123;複製代碼
轉化成napi模式變成了這樣:
napi_status status = napi_generic_failure;
// const obj = {}
napi_value obj, value;
status = napi_create_object(env, &obj);
if (status != napi_ok) return status;
// Create a napi_value for 123
status = napi_create_number(env, 123, &value);
if (status != napi_ok) return status;
// obj.myProp = 123
status = napi_set_named_property(env, obj, "myProp", value);
if (status != napi_ok) return status;複製代碼
const arr = [];
arr[123] = 'hello';複製代碼
napi_status status = napi_generic_failure;
// const arr = []
napi_value arr, value;
status = napi_create_array(env, &arr);
if (status != napi_ok) return status;
// const value = arr[123]
status = napi_get_element(env, arr, 123, &value);
if (status != napi_ok) return status;複製代碼
const obj = {};
Object.defineProperties(obj, {
'foo': { value: 123, writable: true, configurable: true, enumerable: true },
'bar': { value: 456, writable: true, configurable: true, enumerable: true }
});複製代碼
napi的格式爲:
napi_status status = napi_status_generic_failure;
// const obj = {};
napi_value obj;
status = napi_create_obj(env, &obj);
if (status != napi_ok) return status;
// Create napi_values for 123 and 456
napi_value fooValue, barValue;
status = napi_create_number(env, 123, &fooValue);
if (status != napi_ok) return status;
status = napi_create_number(env, 456, &barValue);
if (status != napi_ok) return status;
// Set the properties
napi_property_descriptors descriptors[] = {
{ "foo", fooValue, 0, 0, 0, napi_default, 0 },
{ "bar", barValue, 0, 0, 0, napi_default, 0 }
}
status = napi_define_properties(env,
obj,
sizeof(descriptors) / sizeof(descriptors[0]),
descriptors);
if (status != napi_ok) return status;複製代碼
typedef enum {
napi_default = 0,
napi_read_only = 1 << 0,
napi_dont_enum = 1 << 1,
napi_dont_delete = 1 << 2,
napi_static_property = 1 << 10,
} napi_property_attributes;複製代碼
該結構體是用於控制JavaScript對象上設置的屬性的行爲的標誌的,每一個屬性的示例參見官方傳送門
typedef struct {
const char* utf8name;
napi_callback method;
napi_callback getter;
napi_callback setter;
napi_value value;
napi_property_attributes attributes;
void* data;
} napi_property_descriptor;複製代碼
該結構體用來描述複雜對象具體的屬性,每一個參數的含義參見官方 傳送門
napi_get_property_names
napi_status napi_get_property_names(napi_env env,napi_value object,napi_value* result);
至關於es6中的keys函數
napi_set_property
napi_status napi_set_property(napi_env env,napi_value object,napi_value key,napi_value value);
爲對象的某個屬性賦值
napi_get_property
napi_status napi_get_property(napi_env env,napi_value object,napi_value key,napi_value* result);
獲取對象某個屬性的值
napi_has_property
napi_status napi_has_property(napi_env env,napi_value object,napi_value key,bool* result);
檢測該對象是否存在對應的鍵
napi_set_named_property
napi_status napi_set_named_property(napi_env env,napi_value object,const char* utf8Name,napi_value value);
等價於直接調用napi_set_property,不過限定了字符串爲鍵名的狀況
napi_get_named_property
napi_status napi_get_named_property(napi_env env,napi_value object,const char utf8Name,napi_value result);
等價於調用napi_get_property,限定於字符串爲鍵名的狀況
napi_has_named_property
napi_status napi_has_named_property(napi_env env,napi_value object,const char utf8Name,bool result);
等價於調用napi_has_property,限定於字符串鍵名狀況
napi_set_element
napi_status napi_set_element(napi_env env,napi_value object,uint32_t index,napi_value value);
爲一個對象設置索引鍵屬性
napi_get_element
napi_status napi_get_element(napi_env env,napi_value object,uint32_t index,napi_value* result);
獲取一個對象的索引屬性
napi_has_element
napi_status napi_has_element(napi_env env,napi_value object,uint32_t index,bool* result);
查詢函數是否包含某個索引複製代碼
napi_define_properties
napi_status napi_define_properties(napi_env env,napi_value object,size_t property_count,const napi_property_descriptor* properties);
這個函數用於高效的建立複雜對象,傳入napi_property_descriptor數組,用於建立複雜對象
Napi提供了一些列的api,來容許JavaScript調用本機代碼,使用napi_callback類型表示回調函數。這類api容許回調函數進行一下操做:
另外,napi還提供了一組容許本地代碼調用JavaScript函數的函數,能夠調用像常規JavaScript函數或做爲構造函數的函數
napi_call_function
napi_status napi_call_function(napi_env env,napi_value recv,napi_value func,int argc,const napi_value argv,napi_value result)
該函數用於調用js函數,好比如下示例,即是從全局對象中獲取了全局js函數,並調用。
假設全局存在如下函數:
function AddTwo(num) {
return num + 2;
}複製代碼
而後在下面的代碼中調用:
// Get the function named "AddTwo" on the global object
napi_value global, add_two, arg;
napi_status status = napi_get_global(env, &global);
if (status != napi_ok) return;
status = napi_get_named_property(env, global, "AddTwo", &add_two);
if (status != napi_ok) return;
// const arg = 1337
status = napi_create_number(env, 1337, &arg);
if (status != napi_ok) return;
napi_value* argv = &arg;
size_t argc = 1;
// AddTwo(arg);
napi_value return_val;
status = napi_call_function(env, global, add_two, argc, argv, &return_val);
if (status != napi_ok) return;
// Convert the result back to a native type
int32_t result;
status = napi_get_value_int32(env, return_val, &result);
if (status != napi_ok) return;複製代碼
napi_create_function
napi_status napi_create_function(napi_env env,const char utf8name,napi_callback cb,void data,napi_value* result);
該函數用於建立一個js中能夠調用的函數,示例以下:
void SayHello(napi_env env, napi_callback_info info) {
printf("Hello\n");
}
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_value fn;
status = napi_create_function(env, NULL, SayHello, NULL, &fn);
if (status != napi_ok) return;
status = napi_set_named_property(env, exports, "sayHello", fn);
if (status != napi_ok) return;
}
NAPI_MODULE(addon, Init)複製代碼
napi_get_cb_info
napi_status napi_get_cb_info(napi_env env,napi_callback_info cbinfo,size_t argc,napi_value argv,napi_value thisArg,void* data)
該函數用於在回調函數中從給定的回調信息中檢索有關調用的詳細信息
napi_is_construct_call
napi_status napi_is_construct_call(napi_env env,napi_callback_info cbinfo,bool* result)
該函數用於檢測當前回調是否由構造器調用
napi_new_instance
napi_status napi_new_instance(napi_env env,napi_value cons,size_t argc,napi_value argv,napi_value result)
該函數用於使用給定的napi_value來實例化一個新的JavaScript值,該值表明該對象的構造函數。示例以下:
function MyObject(param) {
this.param = param;
}
const arg = 'hello';
const value = new MyObject(arg);複製代碼
在napi中使用該構造函數大體就是這樣:
// Get the constructor function MyObject
napi_value global, constructor, arg, value;
napi_status status = napi_get_global(env, &global);
if (status != napi_ok) return;
status = napi_get_named_property(env, global, "MyObject", &constructor);
if (status != napi_ok) return;
// const arg = "hello"
status = napi_create_string_utf8(env, "hello", -1, &arg);
if (status != napi_ok) return;
napi_value* argv = &arg;
size_t argc = 1;
// const value = new MyObject(arg)
status = napi_new_instance(env, constructor, argc, argv, &value);複製代碼
napi_make_callback
napi_status napi_make_callback(napi_env env,napi_value recv,napi_value func,int argc,const napi_value argv,napi_value result)
該方法容許從本機插件調用JavaScript函數對象。 這個API相似於napi_call_function。 可是,當從異步操做返回時(當堆棧中沒有其餘腳本)時,它用於從本機代碼調用回JavaScript
napi提供了一種"包裝"C++類和實例的方法,以便於在JavaScript中調用類構造函數和方法.
napi_define_class api定義了一個具備構造函數、靜態屬性和方法的JavaScript類,以及與c++類對應的實例屬性和方法。當JavaScript調用構造函數時,會使用napi_wrap將一個新的c++實例包裝在一個JavaScript對像中,而後返回包裝對象,當訪問對應的方法或屬性訪問器時,調用相應的napi_callback C++函數。
ps:因爲對象包裹的內容很麻煩,因此並未在本文中探討
napi_define_class
napi_status napi_define_class(napi_env env,
const char* utf8name, napi_callback constructor, void* data, size_t property_count, const napi_property_descriptor* properties, napi_value* result);複製代碼
napi_wrap
napi_status napi_wrap(napi_env env,
napi_value js_object, void* native_object, napi_finalize finalize_cb, void* finalize_hint, napi_ref* result);複製代碼
napi_unwrap
napi_status napi_unwrap(napi_env env,napi_value js_object,void** result);
在napi中實現了一系列函數用於管理異步操做,使用napi_create_async_work和napi_delete_async_work建立/刪除實例。
其中執行回調會完成回調分別是在程序準備執行時以及執行完成時所調用的函數:
typedef void (napi_async_execute_callback)(napi_env env,void data);
typedef void (napi_async_complete_callback)(napi_env env,napi_status status,void data);
其中 參數data是調用napi_create_async_work時所傳遞的數據。
建立後可使用napi_queue_async_work函數讓異步工做隊列排隊執行
NAPI_EXTERN napi_status napi_queue_async_work(napi_env env,napi_async_work work);
napi_create_async_work
NAPI_EXTERN
napi_status napi_create_async_work(napi_env env,napi_async_execute_callback execute,napi_async_complete_callback complete,void data,napi_async_work result);
napi_delete_async_work
NAPI_EXTERN napi_status napi_delete_async_work(napi_env env,napi_async_work work);
napi_cancel_async_work
NAPI_EXTERN napi_status napi_cancel_async_work(napi_env env,napi_async_work work);